- add netmap-libpcap
- add netmap (FreeBSD header files need to be updated with this) - move prototype perl scripts to prototype/ folder - create basic structure for sipcap app (no code yet)
This commit is contained in:
169
netmap/LINUX/Makefile
Normal file
169
netmap/LINUX/Makefile
Normal file
@ -0,0 +1,169 @@
|
||||
# To build external modules, you must have a prebuilt kernel available
|
||||
# that contains the configuration and header files used in the build.
|
||||
# go in the kernel directory and do a
|
||||
# make oldconfig; make scripts; make prepare
|
||||
# or make defconfig; make scripts; make prepare
|
||||
#
|
||||
|
||||
|
||||
|
||||
# list of objects for this module
|
||||
#
|
||||
# objects whose source file is in ../sys/dev/netmap
|
||||
remoteobjs := netmap.o netmap_mem2.o \
|
||||
netmap_generic.o netmap_mbq.o netmap_vale.o \
|
||||
netmap_offloadings.o netmap_pipe.o
|
||||
# all objects
|
||||
netmap_lin-objs := $(remoteobjs) netmap_linux.o
|
||||
|
||||
obj-$(CONFIG_NETMAP) = netmap_lin.o
|
||||
|
||||
ifndef NODRIVERS
|
||||
# list of modules to be built (actually also forcedeth and r8169)
|
||||
MOD_LIST:= CONFIG_E1000=m CONFIG_E1000E=m \
|
||||
CONFIG_IXGBE=m CONFIG_IGB=m \
|
||||
CONFIG_BNX2X=m CONFIG_MLX4=m \
|
||||
CONFIG_VIRTIO_NET=m
|
||||
obj-m += $(O_DRIVERS)
|
||||
GET_DRIVERS := get-drivers
|
||||
else
|
||||
MOD_LIST:=
|
||||
endif
|
||||
|
||||
# DRIVER_SRCS names of the driver sources is only used to
|
||||
# clean files that we copied.
|
||||
DRIVER_SRCS = r8169.c forcedeth.c e1000/ e1000e/ ixgbe/ igb/
|
||||
DRIVER_SRCS += bnx2x/ mellanox/ mlx4/ virtio_net.c
|
||||
|
||||
# _DRV_SUBDIRS contains the subdirs with driver sources.
|
||||
# In old linuxes everything is under drivers/net, newer versions
|
||||
# have them in source/drivers/net/ethernet/$(manufacturer)
|
||||
|
||||
_DRV_SUBDIRS= nvidia realtek intel broadcom . ..
|
||||
|
||||
# The following commands are needed to build the modules as out-of-tree,
|
||||
# in fact the kernel sources path must be specified.
|
||||
|
||||
PWD ?= $(CURDIR)
|
||||
M:=$(PWD)
|
||||
|
||||
# Additional compile flags (e.g. header location)
|
||||
EXTRA_CFLAGS := -I$(M) -I$(M)/../sys -I$(M)/../sys/dev -DCONFIG_NETMAP
|
||||
EXTRA_CFLAGS += -Wno-unused-but-set-variable
|
||||
|
||||
# We use KSRC for the kernel configuration and sources.
|
||||
# If the sources are elsewhere, then use SRC to point to them.
|
||||
KSRC ?= /lib/modules/$(shell uname -r)/build
|
||||
SRC ?= $(KSRC)
|
||||
|
||||
# extract version number.
|
||||
# version.h can be in two different places.
|
||||
# NOTE- A.B.C translates to aXXYY where XXYY are hex
|
||||
LIN_VER = $(shell V=linux/version.h; G=. ; \
|
||||
[ -f $(KSRC)/include/$${V} ] || G=generated/uapi ;\
|
||||
grep LINUX_VERSION_CODE $(KSRC)/include/$${G}/linux/version.h | \
|
||||
awk '{printf "%03x%02x", $$3/256, $$3%256} ')
|
||||
|
||||
# produce a list of applicable patches for this version
|
||||
PATCHES := $(shell \
|
||||
cd $(PWD)/patches; ls diff--* | awk -v v=$(LIN_VER) -F -- \
|
||||
'{ if ((!$$3 || $$3 <= v) && (!$$4 || v < $$4)) print $$0; }')
|
||||
|
||||
# source drivers to copy. Names derived from the patches
|
||||
S_DRIVERS := $(shell \
|
||||
cd $(PWD)/patches; ls diff--* | awk -v v=$(LIN_VER) -F -- \
|
||||
'{ if ((!$$3 || $$3 <= v) && (!$$4 || v < $$4)) print $$2 }' )
|
||||
|
||||
# actual drivers after copy and patch
|
||||
DRIVERS = $(shell [ "$(PATCHES)" != "" ] && ls -dAp \
|
||||
`echo $(PATCHES:diff--%=%) | sed -r 's/--[0-9a-f-]+//g'` 2> /dev/null)
|
||||
|
||||
# Compile v1000 (vhost porting to e1000) only if
|
||||
# the LIN_VER >= 3.8.0, because we don't want to deal
|
||||
# with backporting problems for v1000.
|
||||
ifeq ($(word 1, $(sort 30800 $(LIN_VER))), 30800)
|
||||
CONFIG_V1000:=m
|
||||
else
|
||||
CONFIG_V1000:=n
|
||||
endif
|
||||
|
||||
CONFIG_V1000:=n # force disable by now
|
||||
|
||||
obj-$(CONFIG_V1000) += vhost-port/
|
||||
|
||||
|
||||
all: build
|
||||
|
||||
build: $(GET_DRIVERS)
|
||||
$(MAKE) -C $(KSRC) M=$(PWD) CONFIG_NETMAP=m $(MOD_LIST) \
|
||||
EXTRA_CFLAGS='$(EXTRA_CFLAGS)' \
|
||||
O_DRIVERS="$(DRIVERS:%.c=%.o)" modules
|
||||
@ls -l `find . -name \*.ko`
|
||||
|
||||
|
||||
test:
|
||||
@echo "version $(LIN_VER)"
|
||||
@echo "patches $(PATCHES)"
|
||||
@echo "drivers $(DRIVERS)"
|
||||
|
||||
clean:
|
||||
-@ $(MAKE) -C $(KSRC) M=$(PWD) clean 2> /dev/null
|
||||
-@ (rm -rf $(DRIVER_SRCS) *.orig *.rej *.ko *.o .*.d \
|
||||
.tmp_versions *.mod.c modules.order \
|
||||
Module.symvers .*.cmd get-drivers )
|
||||
|
||||
# the source is not here so we need to specify a dependency
|
||||
define remote_template
|
||||
$$(obj)/$(1): $$(M)/../sys/dev/netmap/$(1:.o=.c)
|
||||
$$(call cmd,cc_o_c)
|
||||
$$(call cmd,modversions)
|
||||
endef
|
||||
$(foreach o,$(remoteobjs),$(eval $(call remote_template,$(o))))
|
||||
|
||||
#-- copy and patch initial files
|
||||
# The location changes depending on the OS version, so ...
|
||||
get-drivers:
|
||||
-@( \
|
||||
if [ -d "$(DRIVER_SRC)" ] ; then \
|
||||
cd "$(DRIVER_SRC)"; s=.; what="`ls -dp *`" ; \
|
||||
else \
|
||||
cd $(SRC); [ -d source ] && cd source ; \
|
||||
cd drivers/net; s=. ; \
|
||||
[ -d ethernet ] && cd ethernet && s="$(_DRV_SUBDIRS)" ; \
|
||||
what="$(S_DRIVERS)" ; \
|
||||
fi ; \
|
||||
echo "LIN_VER $(LIN_VER)" ; \
|
||||
[ "$${what}" = "" ] && echo "-- NO DRIVERS --" && return; \
|
||||
echo "---- Building from `pwd`"; \
|
||||
echo "---- copying $${what} ---" ; \
|
||||
what="$${what} cnic_if.h"; \
|
||||
for i in $$s; do (cd $$i ; \
|
||||
echo " From `pwd` :"; \
|
||||
ls -ldp $${what} 2> /dev/null | sed 's/^/ /' ; \
|
||||
cp -Rp $${what} $(PWD) 2>/dev/null ); \
|
||||
done ; \
|
||||
cd $(PWD) ; \
|
||||
for i in $(PATCHES) ; \
|
||||
do echo "** patch with $$i"; \
|
||||
patch --posix --quiet --force -p1 < patches/$$i; \
|
||||
done ; \
|
||||
echo "Building the following drivers: $(S_DRIVERS)" )
|
||||
@touch get-drivers
|
||||
|
||||
|
||||
test3:
|
||||
@echo "from $(PATCHES) -- to $(MYDRIVERS)"
|
||||
@echo "Drivers is $(DRIVERS)"
|
||||
@echo "Actually have `ls -d $(DRIVERS) 2> /dev/null`"
|
||||
|
||||
# compute the diffs for the original files
|
||||
diffs:
|
||||
@for i in `find . -name \*.orig`; do \
|
||||
diff -urp $$i $${i%.orig} ; \
|
||||
done
|
||||
|
||||
apps:
|
||||
(cd ../examples; $(MAKE))
|
||||
|
||||
+%:
|
||||
@echo $($*)
|
154
netmap/LINUX/README
Normal file
154
netmap/LINUX/README
Normal file
@ -0,0 +1,154 @@
|
||||
# $Id: README 10863 2012-04-11 17:10:39Z luigi $
|
||||
|
||||
NETMAP FOR LINUX
|
||||
----------------
|
||||
|
||||
This directory contains a version of the "netmap" and "VALE" code for Linux.
|
||||
|
||||
Netmap is a BSD-licensed framework that supports line-rate direct packet
|
||||
I/O even on 10GBit/s interfaces (14.88Mpps) with limited system load,
|
||||
and includes a libpcap emulation library to port applications.
|
||||
|
||||
See
|
||||
|
||||
http://info.iet.unipi.it/~luigi/netmap/
|
||||
|
||||
for more details. There you can also find the latest versions
|
||||
of the code and documentation as well as pre-built TinyCore
|
||||
images based on linux 3.0.3 and containing the netmap modules
|
||||
and some test applications.
|
||||
|
||||
This version supports r8169, ixgbe, igb, e1000, e1000e and forcedeth.
|
||||
|
||||
Netmap relies on a kernel module (netmap_lin.ko) and slightly modified
|
||||
device drivers. Userspace programs can use the native API (documented
|
||||
in netmap.4) or a libpcap emulation library.
|
||||
|
||||
The FreeBSD and Linux versions share the same codebase, which
|
||||
is located in ../sys . For Linux we use some additional glue code,
|
||||
(bsd_glue.h).
|
||||
|
||||
Device drivers are taken directly from the Linux distributions,
|
||||
and patched using the files in the patches/ directory.
|
||||
Common driver modifications are in the .h files in this directory.
|
||||
|
||||
|
||||
HOW TO BUILD THE CODE
|
||||
---------------------
|
||||
|
||||
1. make sure you have kernel sources/headers matching your installed system
|
||||
|
||||
2. do the following
|
||||
make clean; make KSRC=/usr/src/linux-kernel-source-or-headers
|
||||
this produces ./netmap_lin.ko and other kernel modules.
|
||||
|
||||
3. to build sample applications, run
|
||||
(cd ../examples; make )
|
||||
(you will need the pthreads and libpcap-dev packages to build them)
|
||||
|
||||
If you want support for additional drivers please have a look at
|
||||
ixgbe_netmap_linux.h and the patches in patches/
|
||||
The patch file are named as diff--DRIVER--LOW--HIGH--otherstuff
|
||||
where DRIVER is the driver name to patch, LOW and HIGH are the
|
||||
versions to which the patch applies (LOW included, HIGH excluded, so
|
||||
diff--r8169.c--20638--30300--ok applies from 2.6.38 to 3.3.0 (excluded)
|
||||
|
||||
HOW TO USE THE CODE
|
||||
-------------------
|
||||
|
||||
REMEMBER
|
||||
THIS IS EXPERIMENTAL CODE WHICH MAY CRASH YOUR SYSTEM.
|
||||
USE IT AT YOUR OWN RISk.
|
||||
|
||||
Whether you built your own modules, or are using the prebuilt
|
||||
TinyCore image, the following steps can be used for initial testing:
|
||||
|
||||
1. unload any modules for the network cards you want to use, e.g.
|
||||
sudo rmmod ixgbe
|
||||
sudo rmmod e1000
|
||||
...
|
||||
|
||||
2. load netmap and device driver module
|
||||
sudo insmod ./netmap_lin.ko
|
||||
sudo insmod ./ixgbe/ixgbe.ko
|
||||
sudo insmod ./e1000/e1000.ko
|
||||
...
|
||||
|
||||
3. turn the interface(s) up
|
||||
|
||||
sudo ifconfig eth0 up # and same for others
|
||||
|
||||
4. Run test applications -- as an example, pkt-gen is a raw packet
|
||||
sender/receiver which can do line rate on a 10G interface
|
||||
|
||||
# send about 500 million packets of 60 bytes each.
|
||||
# wait 5s before starting, so the link can go up
|
||||
sudo pkt-gen -i eth0 -f tx -n 500111222 -l 60 -w 5
|
||||
# you should see about 14.88 Mpps
|
||||
|
||||
sudo pkt-gen -i eth0 -f rx # act as a receiver
|
||||
|
||||
|
||||
COMMON PROBLEMS
|
||||
----------------
|
||||
|
||||
* switching in/out of netmap mode causes the link to go down and up.
|
||||
If your card is connected to a switch with spanning tree enabled,
|
||||
the switch will likely MUTE THE LINK FOR 10 SECONDS while it is
|
||||
detecting the new topology. Either disable the spanning tree on
|
||||
the switch or use long pauses before sending data;
|
||||
|
||||
* Not all cards can do line rate no matter how fast is your software or
|
||||
CPU. Several have hardware limitations that prevent reaching the peak
|
||||
speed, especially for small packet sizes. Examples:
|
||||
|
||||
- ixgbe cannot receive at line rate with packet sizes that are
|
||||
not multiple of 64 (after CRC stripping).
|
||||
This is especially evident with minimum-sized frames (-l 60 )
|
||||
|
||||
- some of the low-end 'e1000' cards can send 1.2 - 1.3Mpps instead
|
||||
of the theoretical maximum (1.488Mpps)
|
||||
|
||||
- the 'realtek' cards seem unable to send more than 450-500Kpps
|
||||
even though they can receive at least 1.1Mpps
|
||||
|
||||
* if the link is not up when the packet generator starts, you will
|
||||
see frequent messages about a link reset. While we work on a fix,
|
||||
use the '-w' argument on the generator to specify a longer timeout
|
||||
|
||||
* the ixgbe driver (and perhaps others) is severely slowed down if the
|
||||
remote party is senting flow control frames to slow down traffic.
|
||||
If that happens try to use the ethtool command to disable flow control.
|
||||
|
||||
|
||||
REVISION HISTORY
|
||||
-----------------
|
||||
|
||||
20120813 - updated distribution using common code for FreeBSD and Linux,
|
||||
and inclusion of drivers from the linux source tree
|
||||
|
||||
20120322 - fixed the 'igb' driver, now it can send and receive correctly
|
||||
(the problem was in netmap_rx_irq() so it might have affected
|
||||
other multiqueue cards).
|
||||
Also tested the 'r8169' in transmit mode.
|
||||
Added comments on switches and spanning tree.
|
||||
|
||||
20120217 - initial version. Only ixgbe, e1000 and e1000e are working.
|
||||
Other drivers (igb, r8169, forcedeth) are supplied only as a
|
||||
proof of concept.
|
||||
|
||||
DETAILS
|
||||
--------
|
||||
+ igb: on linux 3.2 and above the igb driver moved to split buffers,
|
||||
and netmap was not updated until end of june 2013.
|
||||
Symptoms were inability to receive short packets.
|
||||
|
||||
+ there are reports of ixgbe and igb unable to read packets.
|
||||
We are unable to reproduce the problem.
|
||||
- Ubuntu 12.04 LTS 3.5.0-25-generic. igb read problems ?
|
||||
- 3.2.0-32-generic with 82598 not working
|
||||
|
||||
+ if_e1000_e uses regular descriptor up 3.1 at least
|
||||
3.2.32 is reported to use extended descriptors
|
||||
(in my repo updated at -r 11975)
|
||||
|
74
netmap/LINUX/archlinux/PKGBUILD
Normal file
74
netmap/LINUX/archlinux/PKGBUILD
Normal file
@ -0,0 +1,74 @@
|
||||
# See http://wiki.archlinux.org/index.php/VCS_PKGBUILD_Guidelines
|
||||
# for more information on packaging from GIT sources.
|
||||
|
||||
# Maintainer: Vincenzo Maffione <v.maffione@gmail.com>
|
||||
pkgname=netmap
|
||||
pkgver=2.0
|
||||
pkgrel=1
|
||||
pkgdesc="Netmap is a framework for high speed network packet I/O."
|
||||
arch=('any')
|
||||
url="http://info.iet.unipi.it/~luigi/netmap"
|
||||
license=('BSD')
|
||||
groups=()
|
||||
depends=('linux' 'glibc')
|
||||
makedepends=('git' 'sed' 'gzip' 'linux-headers')
|
||||
provides=()
|
||||
conflicts=()
|
||||
replaces=()
|
||||
backup=()
|
||||
options=()
|
||||
install="netmap.install"
|
||||
source=()
|
||||
noextract=()
|
||||
md5sums=() #generate with 'makepkg -g'
|
||||
|
||||
_gitroot="https://v.maffione@code.google.com/p/netmap/"
|
||||
_gitname="netmap"
|
||||
|
||||
build() {
|
||||
cd "$srcdir"
|
||||
msg "Connecting to GIT server...."
|
||||
|
||||
if [[ -d "$_gitname" ]]; then
|
||||
cd "$_gitname" && git pull origin
|
||||
msg "The local files are updated."
|
||||
else
|
||||
git clone "$_gitroot" "$_gitname"
|
||||
fi
|
||||
|
||||
msg "GIT checkout done or server timeout"
|
||||
msg "Starting build..."
|
||||
|
||||
rm -rf "$srcdir/$_gitname-build"
|
||||
git clone "$srcdir/$_gitname" "$srcdir/$_gitname-build"
|
||||
cd "$srcdir/$_gitname-build"
|
||||
|
||||
# Build the netmap kernel module
|
||||
cd "$srcdir/$_gitname-build/LINUX"
|
||||
make || return 1
|
||||
# Build pkt-gen and vale-ctl
|
||||
cd "$srcdir/$_gitname-build/examples"
|
||||
make pkt-gen vale-ctl || return 1
|
||||
}
|
||||
|
||||
package() {
|
||||
# Compute the version numbers of the running kernel
|
||||
KVER1=$(uname -r)
|
||||
KVER2=$(uname -r | sed 's/\.[0-9]\+-[0-9]\+//')
|
||||
|
||||
# Install the netmap module into the extramodules-VERSION directory
|
||||
mkdir -p "$pkgdir/lib/modules/extramodules-${KVER2}"
|
||||
cp "$srcdir/$_gitname-build/LINUX/netmap_lin.ko" "$pkgdir/lib/modules/extramodules-${KVER2}"
|
||||
|
||||
# Install pkt-gen and valectl into /usr/bin
|
||||
mkdir -p "$pkgdir/usr/bin"
|
||||
cp "$srcdir/$_gitname-build/examples/pkt-gen" "$pkgdir/usr/bin"
|
||||
cp "$srcdir/$_gitname-build/examples/vale-ctl" "$pkgdir/usr/bin"
|
||||
|
||||
# Install the netmap man page
|
||||
mkdir -p "$pkgdir/usr/share/man/man4"
|
||||
cp "$srcdir/$_gitname-build/share/man/man4/netmap.4" "$pkgdir/usr/share/man/man4"
|
||||
gzip "$pkgdir/usr/share/man/man4/netmap.4"
|
||||
}
|
||||
|
||||
# vim:set ts=2 sw=2 et:
|
20
netmap/LINUX/archlinux/netmap.install
Normal file
20
netmap/LINUX/archlinux/netmap.install
Normal file
@ -0,0 +1,20 @@
|
||||
post_common() {
|
||||
depmod -a
|
||||
}
|
||||
|
||||
## arg 1: the new package version
|
||||
post_install() {
|
||||
post_common
|
||||
}
|
||||
|
||||
## arg 1: the new package version
|
||||
## arg 2: the old package version
|
||||
post_upgrade() {
|
||||
post_common
|
||||
}
|
||||
|
||||
## arg 1: the old package version
|
||||
post_remove() {
|
||||
post_common
|
||||
}
|
||||
|
424
netmap/LINUX/bsd_glue.h
Normal file
424
netmap/LINUX/bsd_glue.h
Normal file
@ -0,0 +1,424 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2014 Luigi Rizzo - Universita` di Pisa
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* glue code to build the netmap bsd code under linux.
|
||||
* Some of these tweaks are generic, some are specific for
|
||||
* character device drivers and network code/device drivers.
|
||||
*/
|
||||
|
||||
#ifndef _BSD_GLUE_H
|
||||
#define _BSD_GLUE_H
|
||||
|
||||
/* a set of headers used in netmap */
|
||||
#include <linux/version.h>
|
||||
#include <linux/compiler.h> // ACCESS_ONCE()
|
||||
|
||||
#include <linux/if.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/etherdevice.h> // eth_type_trans
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/virtio.h> // virt_to_phys
|
||||
#include <net/sock.h>
|
||||
#include <linux/delay.h> // msleep
|
||||
#include <linux/skbuff.h> // skb_copy_to_linear_data_offset
|
||||
|
||||
#include <linux/io.h> // virt_to_phys
|
||||
#include <linux/hrtimer.h>
|
||||
|
||||
#define printf(fmt, arg...) printk(KERN_ERR fmt, ##arg)
|
||||
#define KASSERT(a, b) BUG_ON(!(a))
|
||||
|
||||
/*----- support for compiling on older versions of linux -----*/
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 21)
|
||||
#define HRTIMER_MODE_REL HRTIMER_REL
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
|
||||
#define skb_copy_from_linear_data_offset(skb, offset, to, copy) \
|
||||
memcpy(to, (skb)->data + offset, copy)
|
||||
|
||||
#define skb_copy_to_linear_data_offset(skb, offset, from, copy) \
|
||||
memcpy((skb)->data + offset, from, copy)
|
||||
|
||||
#define skb_copy_to_linear_data(skb, from, copy) \
|
||||
memcpy((skb)->data, from, copy)
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
|
||||
#define ACCESS_ONCE(x) (x)
|
||||
#define uintptr_t unsigned long
|
||||
#define skb_get_queue_mapping(m) (0)
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
|
||||
/* Forward a hrtimer so it expires after the hrtimer's current now */
|
||||
static inline u64 hrtimer_forward_now(struct hrtimer *timer,
|
||||
ktime_t interval)
|
||||
{
|
||||
return hrtimer_forward(timer, timer->base->get_time(), interval);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27)
|
||||
typedef unsigned long phys_addr_t;
|
||||
extern struct net init_net;
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28) // XXX
|
||||
#define netdev_ops hard_start_xmit
|
||||
struct net_device_ops {
|
||||
int (*ndo_start_xmit)(struct sk_buff *skb, struct net_device *dev);
|
||||
};
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32) // XXX 31
|
||||
#define netdev_tx_t int
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
|
||||
#define usleep_range(a, b) msleep((a)+(b)+999)
|
||||
#endif /* up to 2.6.35 */
|
||||
|
||||
/*----------- end of LINUX_VERSION_CODE dependencies ----------*/
|
||||
|
||||
/* Type redefinitions. XXX check them */
|
||||
typedef void * bus_dma_tag_t;
|
||||
typedef void * bus_dmamap_t;
|
||||
typedef int bus_size_t;
|
||||
typedef int bus_dma_segment_t;
|
||||
typedef void * bus_addr_t;
|
||||
#define vm_paddr_t phys_addr_t
|
||||
/* XXX the 'off_t' on Linux corresponds to a 'long' */
|
||||
#define vm_offset_t uint32_t
|
||||
#define vm_ooffset_t unsigned long
|
||||
struct thread;
|
||||
|
||||
/* endianness macros/functions */
|
||||
#define le16toh le16_to_cpu
|
||||
#define le32toh le32_to_cpu
|
||||
#define le64toh le64_to_cpu
|
||||
#define be16toh be16_to_cpu
|
||||
#define be32toh be32_to_cpu
|
||||
#define be64toh be64_to_cpu
|
||||
#define htole32 cpu_to_le32
|
||||
#define htole64 cpu_to_le64
|
||||
#define htobe16 cpu_to_be16
|
||||
#define htobe32 cpu_to_be32
|
||||
|
||||
#include <linux/jiffies.h>
|
||||
#define time_second (jiffies_to_msecs(jiffies) / 1000U )
|
||||
|
||||
#define bzero(a, len) memset(a, 0, len)
|
||||
|
||||
/* Atomic variables. */
|
||||
#define NM_ATOMIC_TEST_AND_SET(p) test_and_set_bit(0, (p))
|
||||
#define NM_ATOMIC_CLEAR(p) clear_bit(0, (p))
|
||||
|
||||
#define NM_ATOMIC_SET(p, v) atomic_set(p, v)
|
||||
#define NM_ATOMIC_INC(p) atomic_inc(p)
|
||||
#define NM_ATOMIC_READ_AND_CLEAR(p) atomic_xchg(p, 0)
|
||||
#define NM_ATOMIC_READ(p) atomic_read(p)
|
||||
|
||||
|
||||
// XXX maybe implement it as a proper function somewhere
|
||||
// it is important to set s->len before the copy.
|
||||
#define m_devget(_buf, _len, _ofs, _dev, _fn) ( { \
|
||||
struct sk_buff *s = netdev_alloc_skb(_dev, _len); \
|
||||
if (s) { \
|
||||
skb_put(s, _len); \
|
||||
skb_copy_to_linear_data_offset(s, _ofs, _buf, _len); \
|
||||
s->protocol = eth_type_trans(s, _dev); \
|
||||
} \
|
||||
s; } )
|
||||
|
||||
#define mbuf sk_buff
|
||||
#define m_nextpkt next // chain of mbufs
|
||||
#define m_freem(m) dev_kfree_skb_any(m) // free a sk_buff
|
||||
|
||||
#define GET_MBUF_REFCNT(m) NM_ATOMIC_READ(&((m)->users))
|
||||
#define netmap_get_mbuf(size) alloc_skb(size, GFP_ATOMIC)
|
||||
/*
|
||||
* on tx we force skb->queue_mapping = ring_nr,
|
||||
* but on rx it is the driver that sets the value,
|
||||
* and it is 0 for no setting, ring_nr+1 otherwise.
|
||||
*/
|
||||
#define MBUF_TXQ(m) skb_get_queue_mapping(m)
|
||||
#define MBUF_RXQ(m) (skb_rx_queue_recorded(m) ? skb_get_rx_queue(m) : 0)
|
||||
#define SET_MBUF_DESTRUCTOR(m, f) m->destructor = (void *)&f
|
||||
|
||||
/* Magic number for sk_buff.priority field, used to take decisions in
|
||||
* generic_ndo_start_xmit() and in linux_generic_rx_handler().
|
||||
*/
|
||||
#define NM_MAGIC_PRIORITY_TX 0xad86d310U
|
||||
#define NM_MAGIC_PRIORITY_RX 0xad86d311U
|
||||
|
||||
/*
|
||||
* m_copydata() copies from mbuf to buffer following the mbuf chain.
|
||||
* skb_copy_bits() copies the skb headlen and all the fragments.
|
||||
*/
|
||||
|
||||
#define m_copydata(m, o, l, b) skb_copy_bits(m, o, b, l)
|
||||
|
||||
#define copyin(_from, _to, _len) copy_from_user(_to, _from, _len)
|
||||
|
||||
/*
|
||||
* struct ifnet is remapped into struct net_device on linux.
|
||||
* ifnet has an if_softc field pointing to the device-specific struct
|
||||
* (adapter).
|
||||
* On linux the ifnet/net_device is at the beginning of the device-specific
|
||||
* structure, so a pointer to the first field of the ifnet works.
|
||||
* We don't use this in netmap, though.
|
||||
*
|
||||
* if_xname name device name
|
||||
* if_capenable priv_flags
|
||||
* we would use "features" but it is all taken.
|
||||
* XXX check for conflict in flags use.
|
||||
*
|
||||
* In netmap we use if_pspare[0] to point to the netmap_adapter,
|
||||
* in linux we have no spares so we overload ax25_ptr, and the detection
|
||||
* for netmap-capable is some magic in the area pointed by that.
|
||||
*/
|
||||
#define WNA(_ifp) (_ifp)->ax25_ptr
|
||||
|
||||
#define ifnet net_device /* remap */
|
||||
#define if_xname name /* field ifnet-> net_device */
|
||||
#define if_capenable priv_flags /* IFCAP_NETMAP */
|
||||
|
||||
/* some other FreeBSD APIs */
|
||||
struct net_device* ifunit_ref(const char *name);
|
||||
void if_rele(struct net_device *ifp);
|
||||
|
||||
/* hook to send from user space */
|
||||
netdev_tx_t linux_netmap_start_xmit(struct sk_buff *, struct net_device *);
|
||||
|
||||
/* prevent ring params change while in netmap mode */
|
||||
int linux_netmap_set_ringparam(struct net_device *, struct ethtool_ringparam *);
|
||||
#ifdef ETHTOOL_SCHANNELS
|
||||
int linux_netmap_set_channels(struct net_device *, struct ethtool_channels *);
|
||||
#endif
|
||||
|
||||
#define CURVNET_SET(x)
|
||||
#define CURVNET_RESTORE(x)
|
||||
|
||||
#define refcount_acquire(_a) atomic_add(1, (atomic_t *)_a)
|
||||
#define refcount_release(_a) atomic_dec_and_test((atomic_t *)_a)
|
||||
|
||||
|
||||
/*
|
||||
* We use spin_lock_irqsave() because we use the lock in the
|
||||
* (hard) interrupt context.
|
||||
*/
|
||||
typedef struct {
|
||||
spinlock_t sl;
|
||||
ulong flags;
|
||||
} safe_spinlock_t;
|
||||
|
||||
static inline void mtx_lock(safe_spinlock_t *m)
|
||||
{
|
||||
spin_lock_irqsave(&(m->sl), m->flags);
|
||||
}
|
||||
|
||||
static inline void mtx_unlock(safe_spinlock_t *m)
|
||||
{
|
||||
ulong flags = ACCESS_ONCE(m->flags);
|
||||
spin_unlock_irqrestore(&(m->sl), flags);
|
||||
}
|
||||
|
||||
#define mtx_init(a, b, c, d) spin_lock_init(&((a)->sl))
|
||||
#define mtx_destroy(a) // XXX spin_lock_destroy(a)
|
||||
|
||||
/*
|
||||
* XXX these must be changed, as we cannot sleep within the RCU.
|
||||
* Must change to proper rwlock, and then can move the definitions
|
||||
* into the main netmap.c file.
|
||||
*/
|
||||
#define BDG_RWLOCK_T struct rw_semaphore
|
||||
#define BDG_RWINIT(b) init_rwsem(&(b)->bdg_lock)
|
||||
#define BDG_WLOCK(b) down_write(&(b)->bdg_lock)
|
||||
#define BDG_WUNLOCK(b) up_write(&(b)->bdg_lock)
|
||||
#define BDG_RLOCK(b) down_read(&(b)->bdg_lock)
|
||||
#define BDG_RUNLOCK(b) up_read(&(b)->bdg_lock)
|
||||
#define BDG_RTRYLOCK(b) down_read_trylock(&(b)->bdg_lock)
|
||||
#define BDG_SET_VAR(lval, p) ((lval) = (p))
|
||||
#define BDG_GET_VAR(lval) (lval)
|
||||
#define BDG_FREE(p) kfree(p)
|
||||
|
||||
/* use volatile to fix a probable compiler error on 2.6.25 */
|
||||
#define malloc(_size, type, flags) \
|
||||
({ volatile int _v = _size; kmalloc(_v, GFP_ATOMIC | __GFP_ZERO); })
|
||||
|
||||
#define free(a, t) kfree(a)
|
||||
|
||||
// XXX do we need GPF_ZERO ?
|
||||
// XXX do we need GFP_DMA for slots ?
|
||||
// http://www.mjmwired.net/kernel/Documentation/DMA-API.txt
|
||||
|
||||
#ifndef ilog2 /* not in 2.6.18 */
|
||||
static inline int ilog2(uint64_t n)
|
||||
{
|
||||
uint64_t k = 1ULL<<63;
|
||||
int i;
|
||||
for (i = 63; i >= 0 && !(n &k); i--, k >>=1)
|
||||
;
|
||||
return i;
|
||||
}
|
||||
#endif /* ilog2 */
|
||||
|
||||
#define contigmalloc(sz, ty, flags, a, b, pgsz, c) \
|
||||
(char *) __get_free_pages(GFP_ATOMIC | __GFP_ZERO, \
|
||||
ilog2(roundup_pow_of_two((sz)/PAGE_SIZE)))
|
||||
#define contigfree(va, sz, ty) free_pages((unsigned long)va, \
|
||||
ilog2(roundup_pow_of_two(sz)/PAGE_SIZE))
|
||||
|
||||
#define vtophys virt_to_phys
|
||||
|
||||
/*--- selrecord and friends ---*/
|
||||
/* wake_up() or wake_up_interruptible() ? */
|
||||
#define OS_selwakeup(sw, pri) wake_up(sw)
|
||||
#define selrecord(x, y) poll_wait((struct file *)x, y, pwait)
|
||||
|
||||
// #define knlist_destroy(x) // XXX todo
|
||||
|
||||
#define tsleep(a, b, c, t) msleep(10)
|
||||
// #define wakeup(sw) // XXX double check
|
||||
|
||||
#define microtime do_gettimeofday // debugging
|
||||
|
||||
|
||||
/*
|
||||
* The following trick is to map a struct cdev into a struct miscdevice
|
||||
* On FreeBSD cdev and cdevsw are two different objects.
|
||||
*/
|
||||
#define cdev miscdevice
|
||||
#define cdevsw miscdevice
|
||||
|
||||
|
||||
/*
|
||||
* XXX to complete - the dmamap interface
|
||||
*/
|
||||
#define BUS_DMA_NOWAIT 0
|
||||
#define bus_dmamap_load(_1, _2, _3, _4, _5, _6, _7)
|
||||
#define bus_dmamap_unload(_1, _2)
|
||||
|
||||
typedef int (d_mmap_t)(struct file *f, struct vm_area_struct *vma);
|
||||
typedef unsigned int (d_poll_t)(struct file * file, struct poll_table_struct *pwait);
|
||||
|
||||
/*
|
||||
* make_dev will set an error and return the first argument.
|
||||
* This relies on the availability of the 'error' local variable.
|
||||
* For old linux systems that do not have devfs, generate a
|
||||
* message in syslog so the sysadmin knows which command to run
|
||||
* in order to create the /dev/netmap entry
|
||||
*/
|
||||
#define make_dev(_cdev, _zero, _uid, _gid, _perm, _name) \
|
||||
({error = misc_register(_cdev); \
|
||||
D("run mknod /dev/%s c %d %d # error %d", \
|
||||
(_cdev)->name, MISC_MAJOR, (_cdev)->minor, error); \
|
||||
_cdev; } )
|
||||
#define destroy_dev(_cdev) misc_deregister(_cdev)
|
||||
|
||||
/*--- sysctl API ----*/
|
||||
/*
|
||||
* linux: sysctl are mapped into /sys/module/ipfw_mod parameters
|
||||
* windows: they are emulated via get/setsockopt
|
||||
*/
|
||||
#define CTLFLAG_RD 1
|
||||
#define CTLFLAG_RW 2
|
||||
|
||||
struct sysctl_oid;
|
||||
struct sysctl_req;
|
||||
|
||||
|
||||
#define SYSCTL_DECL(_1)
|
||||
#define SYSCTL_OID(_1, _2, _3, _4, _5, _6, _7, _8)
|
||||
#define SYSCTL_NODE(_1, _2, _3, _4, _5, _6)
|
||||
#define _SYSCTL_BASE(_name, _var, _ty, _perm) \
|
||||
module_param_named(_name, *(_var), _ty, \
|
||||
( (_perm) == CTLFLAG_RD) ? 0444: 0644 )
|
||||
|
||||
/* XXX should implement this */
|
||||
extern struct kernel_param_ops generic_sysctl_ops;
|
||||
|
||||
#define SYSCTL_PROC(_base, _oid, _name, _mode, _var, _val, _fn, _ty, _desc) \
|
||||
module_param_cb(_name, &generic_sysctl_ops, _fn, \
|
||||
( (_mode) & CTLFLAG_WR) ? 0644: 0444 )
|
||||
|
||||
|
||||
/* for a string, _var is a preallocated buffer of size _varlen */
|
||||
#define SYSCTL_STRING(_base, _oid, _name, _mode, _var, _varlen, _desc) \
|
||||
module_param_string(_name, _var, _varlen, \
|
||||
((_mode) == CTLFLAG_RD) ? 0444: 0644 )
|
||||
|
||||
#define SYSCTL_INT(_base, _oid, _name, _mode, _var, _val, _desc) \
|
||||
_SYSCTL_BASE(_name, _var, int, _mode)
|
||||
|
||||
#define SYSCTL_LONG(_base, _oid, _name, _mode, _var, _val, _desc) \
|
||||
_SYSCTL_BASE(_name, _var, long, _mode)
|
||||
|
||||
#define SYSCTL_ULONG(_base, _oid, _name, _mode, _var, _val, _desc) \
|
||||
_SYSCTL_BASE(_name, _var, ulong, _mode)
|
||||
|
||||
#define SYSCTL_UINT(_base, _oid, _name, _mode, _var, _val, _desc) \
|
||||
_SYSCTL_BASE(_name, _var, uint, _mode)
|
||||
|
||||
// #define TUNABLE_INT(_name, _ptr)
|
||||
|
||||
#define SYSCTL_VNET_PROC SYSCTL_PROC
|
||||
#define SYSCTL_VNET_INT SYSCTL_INT
|
||||
|
||||
#define SYSCTL_HANDLER_ARGS \
|
||||
struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req
|
||||
int sysctl_handle_int(SYSCTL_HANDLER_ARGS);
|
||||
int sysctl_handle_long(SYSCTL_HANDLER_ARGS);
|
||||
|
||||
#define MALLOC_DECLARE(a)
|
||||
#define MALLOC_DEFINE(a, b, c)
|
||||
|
||||
#define devfs_get_cdevpriv(pp) \
|
||||
({ *(struct netmap_priv_d **)pp = ((struct file *)td)->private_data; \
|
||||
(*pp ? 0 : ENOENT); })
|
||||
|
||||
/* devfs_set_cdevpriv cannot fail on linux */
|
||||
#define devfs_set_cdevpriv(p, fn) \
|
||||
({ ((struct file *)td)->private_data = p; (p ? 0 : EINVAL); })
|
||||
|
||||
|
||||
#define devfs_clear_cdevpriv() do { \
|
||||
netmap_dtor(priv); ((struct file *)td)->private_data = 0; \
|
||||
} while (0)
|
||||
|
||||
#endif /* _BSD_GLUE_H */
|
104
netmap/LINUX/final-patches/diff--e1000--20620--99999
Normal file
104
netmap/LINUX/final-patches/diff--e1000--20620--99999
Normal file
@ -0,0 +1,104 @@
|
||||
diff --git a/e1000/e1000_main.c b/e1000/e1000_main.c
|
||||
index bcd192c..5de7009 100644
|
||||
--- a/e1000/e1000_main.c
|
||||
+++ b/e1000/e1000_main.c
|
||||
@@ -213,6 +213,10 @@ static int debug = NETIF_MSG_DRV | NETIF_MSG_PROBE;
|
||||
module_param(debug, int, 0);
|
||||
MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
|
||||
|
||||
+#if defined(CONFIG_NETMAP) || defined(CONFIG_NETMAP_MODULE)
|
||||
+#include <if_e1000_netmap.h>
|
||||
+#endif
|
||||
+
|
||||
/**
|
||||
* e1000_init_module - Driver Registration Routine
|
||||
*
|
||||
@@ -375,6 +379,10 @@ static void e1000_configure(struct e1000_adapter *adapter)
|
||||
e1000_configure_tx(adapter);
|
||||
e1000_setup_rctl(adapter);
|
||||
e1000_configure_rx(adapter);
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (e1000_netmap_init_buffers(adapter))
|
||||
+ return;
|
||||
+#endif /* DEV_NETMAP */
|
||||
/* call E1000_DESC_UNUSED which always leaves
|
||||
* at least 1 descriptor unused to make sure
|
||||
* next_to_use != next_to_clean */
|
||||
@@ -402,6 +410,10 @@ int e1000_up(struct e1000_adapter *adapter)
|
||||
|
||||
netif_wake_queue(adapter->netdev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_enable_all_rings(adapter->netdev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
/* fire a link change interrupt to start the watchdog */
|
||||
ew32(ICS, E1000_ICS_LSC);
|
||||
return 0;
|
||||
@@ -485,6 +497,10 @@ void e1000_down(struct e1000_adapter *adapter)
|
||||
ew32(RCTL, rctl & ~E1000_RCTL_EN);
|
||||
/* flush and sleep below */
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_disable_all_rings(netdev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
netif_tx_disable(netdev);
|
||||
|
||||
/* disable transmits in the hardware */
|
||||
@@ -1035,6 +1051,10 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
|
||||
adapter->wol = adapter->eeprom_wol;
|
||||
device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ e1000_netmap_attach(adapter);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
/* print bus type/speed/width info */
|
||||
DPRINTK(PROBE, INFO, "(PCI%s:%s:%s) ",
|
||||
((hw->bus_type == e1000_bus_type_pcix) ? "-X" : ""),
|
||||
@@ -1113,6 +1133,10 @@ static void __devexit e1000_remove(struct pci_dev *pdev)
|
||||
|
||||
kfree(adapter->tx_ring);
|
||||
kfree(adapter->rx_ring);
|
||||
+
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_detach(netdev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
|
||||
iounmap(hw->hw_addr);
|
||||
if (hw->flash_address)
|
||||
@@ -1291,6 +1315,10 @@ static int e1000_open(struct net_device *netdev)
|
||||
|
||||
netif_start_queue(netdev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_enable_all_rings(netdev);
|
||||
+#endif
|
||||
+
|
||||
/* fire a link status change interrupt to start the watchdog */
|
||||
ew32(ICS, E1000_ICS_LSC);
|
||||
|
||||
@@ -3429,6 +3457,10 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,
|
||||
unsigned int count = 0;
|
||||
unsigned int total_tx_bytes=0, total_tx_packets=0;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (netmap_tx_irq(netdev, 0))
|
||||
+ return 1; /* cleaned ok */
|
||||
+#endif /* DEV_NETMAP */
|
||||
i = tx_ring->next_to_clean;
|
||||
eop = tx_ring->buffer_info[i].next_to_watch;
|
||||
eop_desc = E1000_TX_DESC(*tx_ring, eop);
|
||||
@@ -3795,6 +3827,11 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
|
||||
bool cleaned = false;
|
||||
unsigned int total_rx_bytes=0, total_rx_packets=0;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ ND("calling netmap_rx_irq");
|
||||
+ if (netmap_rx_irq(netdev, 0, work_done))
|
||||
+ return 1; /* seems to be ignored */
|
||||
+#endif /* DEV_NETMAP */
|
||||
i = rx_ring->next_to_clean;
|
||||
rx_desc = E1000_RX_DESC(*rx_ring, i);
|
||||
buffer_info = &rx_ring->buffer_info[i];
|
91
netmap/LINUX/final-patches/diff--e1000e--20620--20623
Normal file
91
netmap/LINUX/final-patches/diff--e1000e--20620--20623
Normal file
@ -0,0 +1,91 @@
|
||||
diff --git a/e1000e/netdev.c b/e1000e/netdev.c
|
||||
index fad8f9e..50f74e2 100644
|
||||
--- a/e1000e/netdev.c
|
||||
+++ b/e1000e/netdev.c
|
||||
@@ -87,6 +87,10 @@ static int e1000_desc_unused(struct e1000_ring *ring)
|
||||
return ring->count + ring->next_to_clean - ring->next_to_use - 1;
|
||||
}
|
||||
|
||||
+#if defined(CONFIG_NETMAP) || defined(CONFIG_NETMAP_MODULE)
|
||||
+#include <if_e1000e_netmap.h>
|
||||
+#endif
|
||||
+
|
||||
/**
|
||||
* e1000_receive_skb - helper function to handle Rx indications
|
||||
* @adapter: board private structure
|
||||
@@ -446,6 +450,10 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
|
||||
bool cleaned = 0;
|
||||
unsigned int total_rx_bytes = 0, total_rx_packets = 0;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (netmap_rx_irq(netdev, 0, work_done))
|
||||
+ return 1; /* seems to be ignored */
|
||||
+#endif /* DEV_NETMAP */
|
||||
i = rx_ring->next_to_clean;
|
||||
rx_desc = E1000_RX_DESC(*rx_ring, i);
|
||||
buffer_info = &rx_ring->buffer_info[i];
|
||||
@@ -624,6 +632,10 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter)
|
||||
unsigned int count = 0;
|
||||
unsigned int total_tx_bytes = 0, total_tx_packets = 0;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (netmap_tx_irq(netdev, 0))
|
||||
+ return 1; /* cleaned ok */
|
||||
+#endif /* DEV_NETMAP */
|
||||
i = tx_ring->next_to_clean;
|
||||
eop = tx_ring->buffer_info[i].next_to_watch;
|
||||
eop_desc = E1000_TX_DESC(*tx_ring, eop);
|
||||
@@ -2632,6 +2644,10 @@ static void e1000_configure(struct e1000_adapter *adapter)
|
||||
e1000_configure_tx(adapter);
|
||||
e1000_setup_rctl(adapter);
|
||||
e1000_configure_rx(adapter);
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (e1000e_netmap_init_buffers(adapter))
|
||||
+ return;
|
||||
+#endif /* DEV_NETMAP */
|
||||
adapter->alloc_rx_buf(adapter, e1000_desc_unused(adapter->rx_ring));
|
||||
}
|
||||
|
||||
@@ -2892,6 +2908,10 @@ void e1000e_down(struct e1000_adapter *adapter)
|
||||
|
||||
netif_stop_queue(netdev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_disable_all_rings(netdev);
|
||||
+#endif
|
||||
+
|
||||
/* disable transmits in the hardware */
|
||||
tctl = er32(TCTL);
|
||||
tctl &= ~E1000_TCTL_EN;
|
||||
@@ -3174,6 +3194,10 @@ static int e1000_open(struct net_device *netdev)
|
||||
|
||||
netif_start_queue(netdev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_enable_all_rings(netdev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
/* fire a link status change interrupt to start the watchdog */
|
||||
ew32(ICS, E1000_ICS_LSC);
|
||||
|
||||
@@ -5227,6 +5251,9 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
|
||||
if (err)
|
||||
goto err_register;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ e1000_netmap_attach(adapter);
|
||||
+#endif /* DEV_NETMAP */
|
||||
/* carrier off reporting is important to ethtool even BEFORE open */
|
||||
netif_carrier_off(netdev);
|
||||
|
||||
@@ -5300,6 +5327,10 @@ static void __devexit e1000_remove(struct pci_dev *pdev)
|
||||
kfree(adapter->tx_ring);
|
||||
kfree(adapter->rx_ring);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_detach(netdev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
iounmap(adapter->hw.hw_addr);
|
||||
if (adapter->hw.flash_address)
|
||||
iounmap(adapter->hw.flash_address);
|
91
netmap/LINUX/final-patches/diff--e1000e--20623--30100
Normal file
91
netmap/LINUX/final-patches/diff--e1000e--20623--30100
Normal file
@ -0,0 +1,91 @@
|
||||
diff --git a/e1000e/netdev.c b/e1000e/netdev.c
|
||||
index 57a7e41..d8bc988 100644
|
||||
--- a/e1000e/netdev.c
|
||||
+++ b/e1000e/netdev.c
|
||||
@@ -435,6 +435,10 @@ static int e1000_desc_unused(struct e1000_ring *ring)
|
||||
return ring->count + ring->next_to_clean - ring->next_to_use - 1;
|
||||
}
|
||||
|
||||
+#if defined(CONFIG_NETMAP) || defined(CONFIG_NETMAP_MODULE)
|
||||
+#include <if_e1000e_netmap.h>
|
||||
+#endif
|
||||
+
|
||||
/**
|
||||
* e1000_receive_skb - helper function to handle Rx indications
|
||||
* @adapter: board private structure
|
||||
@@ -763,6 +767,10 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
|
||||
bool cleaned = 0;
|
||||
unsigned int total_rx_bytes = 0, total_rx_packets = 0;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (netmap_rx_irq(netdev, 0, work_done))
|
||||
+ return 1; /* seems to be ignored */
|
||||
+#endif /* DEV_NETMAP */
|
||||
i = rx_ring->next_to_clean;
|
||||
rx_desc = E1000_RX_DESC(*rx_ring, i);
|
||||
buffer_info = &rx_ring->buffer_info[i];
|
||||
@@ -977,6 +985,10 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter)
|
||||
unsigned int count = 0;
|
||||
unsigned int total_tx_bytes = 0, total_tx_packets = 0;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (netmap_tx_irq(netdev, 0))
|
||||
+ return 1; /* cleaned ok */
|
||||
+#endif /* DEV_NETMAP */
|
||||
i = tx_ring->next_to_clean;
|
||||
eop = tx_ring->buffer_info[i].next_to_watch;
|
||||
eop_desc = E1000_TX_DESC(*tx_ring, eop);
|
||||
@@ -3001,6 +3013,10 @@ static void e1000_configure(struct e1000_adapter *adapter)
|
||||
e1000_configure_tx(adapter);
|
||||
e1000_setup_rctl(adapter);
|
||||
e1000_configure_rx(adapter);
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (e1000e_netmap_init_buffers(adapter))
|
||||
+ return;
|
||||
+#endif /* DEV_NETMAP */
|
||||
adapter->alloc_rx_buf(adapter, e1000_desc_unused(adapter->rx_ring));
|
||||
}
|
||||
|
||||
@@ -3240,6 +3256,10 @@ void e1000e_down(struct e1000_adapter *adapter)
|
||||
|
||||
netif_stop_queue(netdev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_disable_all_rings(netdev);
|
||||
+#endif
|
||||
+
|
||||
/* disable transmits in the hardware */
|
||||
tctl = er32(TCTL);
|
||||
tctl &= ~E1000_TCTL_EN;
|
||||
@@ -3532,6 +3552,10 @@ static int e1000_open(struct net_device *netdev)
|
||||
|
||||
netif_start_queue(netdev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_enable_all_rings(netdev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
adapter->idle_check = true;
|
||||
pm_runtime_put(&pdev->dev);
|
||||
|
||||
@@ -5716,6 +5740,9 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
|
||||
if (err)
|
||||
goto err_register;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ e1000_netmap_attach(adapter);
|
||||
+#endif /* DEV_NETMAP */
|
||||
/* carrier off reporting is important to ethtool even BEFORE open */
|
||||
netif_carrier_off(netdev);
|
||||
|
||||
@@ -5813,6 +5840,10 @@ static void __devexit e1000_remove(struct pci_dev *pdev)
|
||||
kfree(adapter->tx_ring);
|
||||
kfree(adapter->rx_ring);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_detach(netdev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
iounmap(adapter->hw.hw_addr);
|
||||
if (adapter->hw.flash_address)
|
||||
iounmap(adapter->hw.flash_address);
|
91
netmap/LINUX/final-patches/diff--e1000e--30100--30400
Normal file
91
netmap/LINUX/final-patches/diff--e1000e--30100--30400
Normal file
@ -0,0 +1,91 @@
|
||||
diff --git a/e1000e/netdev.c b/e1000e/netdev.c
|
||||
index 2198e61..caf2767 100644
|
||||
--- a/e1000e/netdev.c
|
||||
+++ b/e1000e/netdev.c
|
||||
@@ -452,6 +452,10 @@ static int e1000_desc_unused(struct e1000_ring *ring)
|
||||
return ring->count + ring->next_to_clean - ring->next_to_use - 1;
|
||||
}
|
||||
|
||||
+#if defined(CONFIG_NETMAP) || defined(CONFIG_NETMAP_MODULE)
|
||||
+#include <if_e1000e_netmap.h>
|
||||
+#endif
|
||||
+
|
||||
/**
|
||||
* e1000_receive_skb - helper function to handle Rx indications
|
||||
* @adapter: board private structure
|
||||
@@ -849,6 +853,10 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
|
||||
bool cleaned = 0;
|
||||
unsigned int total_rx_bytes = 0, total_rx_packets = 0;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (netmap_rx_irq(netdev, 0, work_done))
|
||||
+ return 1; /* seems to be ignored */
|
||||
+#endif /* DEV_NETMAP */
|
||||
i = rx_ring->next_to_clean;
|
||||
rx_desc = E1000_RX_DESC(*rx_ring, i);
|
||||
buffer_info = &rx_ring->buffer_info[i];
|
||||
@@ -1066,6 +1074,10 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter)
|
||||
unsigned int count = 0;
|
||||
unsigned int total_tx_bytes = 0, total_tx_packets = 0;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (netmap_tx_irq(netdev, 0))
|
||||
+ return 1; /* cleaned ok */
|
||||
+#endif /* DEV_NETMAP */
|
||||
i = tx_ring->next_to_clean;
|
||||
eop = tx_ring->buffer_info[i].next_to_watch;
|
||||
eop_desc = E1000_TX_DESC(*tx_ring, eop);
|
||||
@@ -3177,6 +3189,10 @@ static void e1000_configure(struct e1000_adapter *adapter)
|
||||
e1000_configure_tx(adapter);
|
||||
e1000_setup_rctl(adapter);
|
||||
e1000_configure_rx(adapter);
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (e1000e_netmap_init_buffers(adapter))
|
||||
+ return;
|
||||
+#endif /* DEV_NETMAP */
|
||||
adapter->alloc_rx_buf(adapter, e1000_desc_unused(adapter->rx_ring),
|
||||
GFP_KERNEL);
|
||||
}
|
||||
@@ -3468,6 +3484,10 @@ void e1000e_down(struct e1000_adapter *adapter)
|
||||
|
||||
netif_stop_queue(netdev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_disable_all_rings(netdev);
|
||||
+#endif
|
||||
+
|
||||
/* disable transmits in the hardware */
|
||||
tctl = er32(TCTL);
|
||||
tctl &= ~E1000_TCTL_EN;
|
||||
@@ -3755,6 +3775,10 @@ static int e1000_open(struct net_device *netdev)
|
||||
|
||||
netif_start_queue(netdev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_enable_all_rings(netdev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
adapter->idle_check = true;
|
||||
pm_runtime_put(&pdev->dev);
|
||||
|
||||
@@ -6147,6 +6171,9 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
|
||||
if (err)
|
||||
goto err_register;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ e1000_netmap_attach(adapter);
|
||||
+#endif /* DEV_NETMAP */
|
||||
/* carrier off reporting is important to ethtool even BEFORE open */
|
||||
netif_carrier_off(netdev);
|
||||
|
||||
@@ -6234,6 +6261,10 @@ static void __devexit e1000_remove(struct pci_dev *pdev)
|
||||
kfree(adapter->tx_ring);
|
||||
kfree(adapter->rx_ring);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_detach(netdev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
iounmap(adapter->hw.hw_addr);
|
||||
if (adapter->hw.flash_address)
|
||||
iounmap(adapter->hw.flash_address);
|
91
netmap/LINUX/final-patches/diff--e1000e--30400--30900
Normal file
91
netmap/LINUX/final-patches/diff--e1000e--30400--30900
Normal file
@ -0,0 +1,91 @@
|
||||
diff --git a/e1000e/netdev.c b/e1000e/netdev.c
|
||||
index 9520a6a..f6f2df6 100644
|
||||
--- a/e1000e/netdev.c
|
||||
+++ b/e1000e/netdev.c
|
||||
@@ -467,6 +467,10 @@ static int e1000_desc_unused(struct e1000_ring *ring)
|
||||
return ring->count + ring->next_to_clean - ring->next_to_use - 1;
|
||||
}
|
||||
|
||||
+#if defined(CONFIG_NETMAP) || defined(CONFIG_NETMAP_MODULE)
|
||||
+#include <if_e1000e_netmap.h>
|
||||
+#endif
|
||||
+
|
||||
/**
|
||||
* e1000_receive_skb - helper function to handle Rx indications
|
||||
* @adapter: board private structure
|
||||
@@ -875,6 +879,10 @@ static bool e1000_clean_rx_irq(struct e1000_ring *rx_ring, int *work_done,
|
||||
bool cleaned = false;
|
||||
unsigned int total_rx_bytes = 0, total_rx_packets = 0;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (netmap_rx_irq(netdev, 0, work_done))
|
||||
+ return 1; /* seems to be ignored */
|
||||
+#endif /* DEV_NETMAP */
|
||||
i = rx_ring->next_to_clean;
|
||||
rx_desc = E1000_RX_DESC_EXT(*rx_ring, i);
|
||||
staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
|
||||
@@ -1129,6 +1137,10 @@ static bool e1000_clean_tx_irq(struct e1000_ring *tx_ring)
|
||||
unsigned int total_tx_bytes = 0, total_tx_packets = 0;
|
||||
unsigned int bytes_compl = 0, pkts_compl = 0;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (netmap_tx_irq(netdev, 0))
|
||||
+ return 1; /* cleaned ok */
|
||||
+#endif /* DEV_NETMAP */
|
||||
i = tx_ring->next_to_clean;
|
||||
eop = tx_ring->buffer_info[i].next_to_watch;
|
||||
eop_desc = E1000_TX_DESC(*tx_ring, eop);
|
||||
@@ -3358,6 +3370,10 @@ static void e1000_configure(struct e1000_adapter *adapter)
|
||||
e1000e_setup_rss_hash(adapter);
|
||||
e1000_setup_rctl(adapter);
|
||||
e1000_configure_rx(adapter);
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (e1000e_netmap_init_buffers(adapter))
|
||||
+ return;
|
||||
+#endif /* DEV_NETMAP */
|
||||
adapter->alloc_rx_buf(rx_ring, e1000_desc_unused(rx_ring), GFP_KERNEL);
|
||||
}
|
||||
|
||||
@@ -3657,6 +3673,10 @@ void e1000e_down(struct e1000_adapter *adapter)
|
||||
|
||||
netif_stop_queue(netdev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_disable_all_rings(netdev);
|
||||
+#endif
|
||||
+
|
||||
/* disable transmits in the hardware */
|
||||
tctl = er32(TCTL);
|
||||
tctl &= ~E1000_TCTL_EN;
|
||||
@@ -3946,6 +3966,10 @@ static int e1000_open(struct net_device *netdev)
|
||||
adapter->tx_hang_recheck = false;
|
||||
netif_start_queue(netdev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_enable_all_rings(netdev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
adapter->idle_check = true;
|
||||
pm_runtime_put(&pdev->dev);
|
||||
|
||||
@@ -6417,6 +6441,9 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
|
||||
if (err)
|
||||
goto err_register;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ e1000_netmap_attach(adapter);
|
||||
+#endif /* DEV_NETMAP */
|
||||
/* carrier off reporting is important to ethtool even BEFORE open */
|
||||
netif_carrier_off(netdev);
|
||||
|
||||
@@ -6504,6 +6531,10 @@ static void __devexit e1000_remove(struct pci_dev *pdev)
|
||||
kfree(adapter->tx_ring);
|
||||
kfree(adapter->rx_ring);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_detach(netdev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
iounmap(adapter->hw.hw_addr);
|
||||
if (adapter->hw.flash_address)
|
||||
iounmap(adapter->hw.flash_address);
|
91
netmap/LINUX/final-patches/diff--e1000e--30900--99999
Normal file
91
netmap/LINUX/final-patches/diff--e1000e--30900--99999
Normal file
@ -0,0 +1,91 @@
|
||||
diff --git a/e1000e/netdev.c b/e1000e/netdev.c
|
||||
index 7e615e2..f9d8a88 100644
|
||||
--- a/e1000e/netdev.c
|
||||
+++ b/e1000e/netdev.c
|
||||
@@ -473,6 +473,10 @@ static int e1000_desc_unused(struct e1000_ring *ring)
|
||||
return ring->count + ring->next_to_clean - ring->next_to_use - 1;
|
||||
}
|
||||
|
||||
+#if defined(CONFIG_NETMAP) || defined(CONFIG_NETMAP_MODULE)
|
||||
+#include <if_e1000e_netmap.h>
|
||||
+#endif
|
||||
+
|
||||
/**
|
||||
* e1000e_systim_to_hwtstamp - convert system time value to hw time stamp
|
||||
* @adapter: board private structure
|
||||
@@ -914,6 +918,10 @@ static bool e1000_clean_rx_irq(struct e1000_ring *rx_ring, int *work_done,
|
||||
bool cleaned = false;
|
||||
unsigned int total_rx_bytes = 0, total_rx_packets = 0;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (netmap_rx_irq(netdev, 0, work_done))
|
||||
+ return 1; /* seems to be ignored */
|
||||
+#endif /* DEV_NETMAP */
|
||||
i = rx_ring->next_to_clean;
|
||||
rx_desc = E1000_RX_DESC_EXT(*rx_ring, i);
|
||||
staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
|
||||
@@ -1203,6 +1211,10 @@ static bool e1000_clean_tx_irq(struct e1000_ring *tx_ring)
|
||||
unsigned int total_tx_bytes = 0, total_tx_packets = 0;
|
||||
unsigned int bytes_compl = 0, pkts_compl = 0;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (netmap_tx_irq(netdev, 0))
|
||||
+ return 1; /* cleaned ok */
|
||||
+#endif /* DEV_NETMAP */
|
||||
i = tx_ring->next_to_clean;
|
||||
eop = tx_ring->buffer_info[i].next_to_watch;
|
||||
eop_desc = E1000_TX_DESC(*tx_ring, eop);
|
||||
@@ -3685,6 +3697,10 @@ static void e1000_configure(struct e1000_adapter *adapter)
|
||||
e1000e_setup_rss_hash(adapter);
|
||||
e1000_setup_rctl(adapter);
|
||||
e1000_configure_rx(adapter);
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (e1000e_netmap_init_buffers(adapter))
|
||||
+ return;
|
||||
+#endif /* DEV_NETMAP */
|
||||
adapter->alloc_rx_buf(rx_ring, e1000_desc_unused(rx_ring), GFP_KERNEL);
|
||||
}
|
||||
|
||||
@@ -3988,6 +4004,10 @@ void e1000e_down(struct e1000_adapter *adapter)
|
||||
|
||||
netif_stop_queue(netdev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_disable_all_rings(netdev);
|
||||
+#endif
|
||||
+
|
||||
/* disable transmits in the hardware */
|
||||
tctl = er32(TCTL);
|
||||
tctl &= ~E1000_TCTL_EN;
|
||||
@@ -4307,6 +4327,10 @@ static int e1000_open(struct net_device *netdev)
|
||||
adapter->tx_hang_recheck = false;
|
||||
netif_start_queue(netdev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_enable_all_rings(netdev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
adapter->idle_check = true;
|
||||
hw->mac.get_link_status = true;
|
||||
pm_runtime_put(&pdev->dev);
|
||||
@@ -6768,6 +6792,9 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
if (err)
|
||||
goto err_register;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ e1000_netmap_attach(adapter);
|
||||
+#endif /* DEV_NETMAP */
|
||||
/* carrier off reporting is important to ethtool even BEFORE open */
|
||||
netif_carrier_off(netdev);
|
||||
|
||||
@@ -6866,6 +6893,10 @@ static void e1000_remove(struct pci_dev *pdev)
|
||||
kfree(adapter->tx_ring);
|
||||
kfree(adapter->rx_ring);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_detach(netdev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
iounmap(adapter->hw.hw_addr);
|
||||
if (adapter->hw.flash_address)
|
||||
iounmap(adapter->hw.flash_address);
|
76
netmap/LINUX/final-patches/diff--forcedeth.c--20626--99999
Normal file
76
netmap/LINUX/final-patches/diff--forcedeth.c--20626--99999
Normal file
@ -0,0 +1,76 @@
|
||||
diff --git a/forcedeth.c b/forcedeth.c
|
||||
index 9c0b1ba..b081d6b 100644
|
||||
--- a/forcedeth.c
|
||||
+++ b/forcedeth.c
|
||||
@@ -1865,12 +1865,25 @@ static void nv_init_tx(struct net_device *dev)
|
||||
}
|
||||
}
|
||||
|
||||
+#if defined(CONFIG_NETMAP) || defined(CONFIG_NETMAP_MODULE)
|
||||
+/* we need a few forward declarations */
|
||||
+static void nv_drain_rxtx(struct net_device *dev);
|
||||
+static int nv_init_ring(struct net_device *dev);
|
||||
+#include <forcedeth_netmap.h>
|
||||
+#endif
|
||||
+
|
||||
static int nv_init_ring(struct net_device *dev)
|
||||
{
|
||||
struct fe_priv *np = netdev_priv(dev);
|
||||
|
||||
nv_init_tx(dev);
|
||||
nv_init_rx(dev);
|
||||
+#ifdef DEV_NETMAP
|
||||
+ forcedeth_netmap_tx_init(np);
|
||||
+ if (forcedeth_netmap_rx_init(np))
|
||||
+ return 0; /* success */
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
|
||||
if (!nv_optimized(np))
|
||||
return nv_alloc_rx(dev);
|
||||
@@ -3386,6 +3399,11 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data)
|
||||
int i;
|
||||
unsigned long flags;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (netmap_tx_irq(dev, 0))
|
||||
+ return IRQ_HANDLED;
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
for (i = 0;; i++) {
|
||||
events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQ_TX_ALL;
|
||||
writel(NVREG_IRQ_TX_ALL, base + NvRegMSIXIrqStatus);
|
||||
@@ -3497,6 +3515,11 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data)
|
||||
int i;
|
||||
unsigned long flags;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (netmap_rx_irq(dev, 0, &i))
|
||||
+ return IRQ_HANDLED;
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
for (i = 0;; i++) {
|
||||
events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQ_RX_ALL;
|
||||
writel(NVREG_IRQ_RX_ALL, base + NvRegMSIXIrqStatus);
|
||||
@@ -5645,6 +5668,10 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
|
||||
goto out_error;
|
||||
}
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ forcedeth_netmap_attach(np);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
netif_carrier_off(dev);
|
||||
|
||||
dev_info(&pci_dev->dev, "ifname %s, PHY OUI 0x%x @ %d, addr %pM\n",
|
||||
@@ -5728,6 +5755,10 @@ static void __devexit nv_remove(struct pci_dev *pci_dev)
|
||||
|
||||
unregister_netdev(dev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_detach(dev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
nv_restore_mac_addr(pci_dev);
|
||||
|
||||
/* restore any phy related changes */
|
37
netmap/LINUX/final-patches/diff--igb--20621--20623
Normal file
37
netmap/LINUX/final-patches/diff--igb--20621--20623
Normal file
@ -0,0 +1,37 @@
|
||||
diff --git a/igb/igb_main.c b/igb/igb_main.c
|
||||
index c881347..77b3fda 100644
|
||||
--- a/igb/igb_main.c
|
||||
+++ b/igb/igb_main.c
|
||||
@@ -1144,6 +1144,10 @@ int igb_up(struct igb_adapter *adapter)
|
||||
|
||||
netif_tx_start_all_queues(adapter->netdev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_enable_all_rings(adapter->netdev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
/* start the watchdog. */
|
||||
hw->mac.get_link_status = 1;
|
||||
schedule_work(&adapter->watchdog_task);
|
||||
@@ -1167,6 +1171,10 @@ void igb_down(struct igb_adapter *adapter)
|
||||
wr32(E1000_RCTL, rctl & ~E1000_RCTL_EN);
|
||||
/* flush and sleep below */
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_disable_all_rings(netdev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
netif_tx_stop_all_queues(netdev);
|
||||
|
||||
/* disable transmits in the hardware */
|
||||
@@ -2018,6 +2026,10 @@ static int igb_open(struct net_device *netdev)
|
||||
|
||||
netif_tx_start_all_queues(netdev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_enable_all_rings(netdev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
/* start the watchdog. */
|
||||
hw->mac.get_link_status = 1;
|
||||
schedule_work(&adapter->watchdog_task);
|
115
netmap/LINUX/final-patches/diff--igb--20623--30200
Normal file
115
netmap/LINUX/final-patches/diff--igb--20623--30200
Normal file
@ -0,0 +1,115 @@
|
||||
diff --git a/igb/igb_main.c b/igb/igb_main.c
|
||||
index cea37e0..70777e4 100644
|
||||
--- a/igb/igb_main.c
|
||||
+++ b/igb/igb_main.c
|
||||
@@ -201,6 +201,10 @@ MODULE_DESCRIPTION("Intel(R) Gigabit Ethernet Network Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(DRV_VERSION);
|
||||
|
||||
+#if defined(CONFIG_NETMAP) || defined(CONFIG_NETMAP_MODULE)
|
||||
+#include <if_igb_netmap.h>
|
||||
+#endif
|
||||
+
|
||||
struct igb_reg_info {
|
||||
u32 ofs;
|
||||
char *name;
|
||||
@@ -1478,6 +1482,10 @@ int igb_up(struct igb_adapter *adapter)
|
||||
|
||||
netif_tx_start_all_queues(adapter->netdev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_enable_all_rings(adapter->netdev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
/* start the watchdog. */
|
||||
hw->mac.get_link_status = 1;
|
||||
schedule_work(&adapter->watchdog_task);
|
||||
@@ -1501,6 +1509,10 @@ void igb_down(struct igb_adapter *adapter)
|
||||
wr32(E1000_RCTL, rctl & ~E1000_RCTL_EN);
|
||||
/* flush and sleep below */
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_disable_all_rings(netdev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
netif_tx_stop_all_queues(netdev);
|
||||
|
||||
/* disable transmits in the hardware */
|
||||
@@ -1963,6 +1975,10 @@ static int __devinit igb_probe(struct pci_dev *pdev,
|
||||
/* carrier off reporting is important to ethtool even BEFORE open */
|
||||
netif_carrier_off(netdev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ igb_netmap_attach(adapter);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
#ifdef CONFIG_IGB_DCA
|
||||
if (dca_add_requester(&pdev->dev) == 0) {
|
||||
adapter->flags |= IGB_FLAG_DCA_ENABLED;
|
||||
@@ -2072,6 +2088,10 @@ static void __devexit igb_remove(struct pci_dev *pdev)
|
||||
dev_info(&pdev->dev, "IOV Disabled\n");
|
||||
}
|
||||
#endif
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_detach(netdev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
|
||||
iounmap(hw->hw_addr);
|
||||
if (hw->flash_address)
|
||||
@@ -2366,6 +2386,10 @@ static int igb_open(struct net_device *netdev)
|
||||
|
||||
netif_tx_start_all_queues(netdev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_enable_all_rings(netdev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
/* start the watchdog. */
|
||||
hw->mac.get_link_status = 1;
|
||||
schedule_work(&adapter->watchdog_task);
|
||||
@@ -2545,6 +2569,9 @@ void igb_configure_tx_ring(struct igb_adapter *adapter,
|
||||
|
||||
txdctl |= E1000_TXDCTL_QUEUE_ENABLE;
|
||||
wr32(E1000_TXDCTL(reg_idx), txdctl);
|
||||
+#ifdef DEV_NETMAP
|
||||
+ igb_netmap_configure_tx_ring(adapter, reg_idx);
|
||||
+#endif /* DEV_NETMAP */
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -5338,6 +5365,11 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector)
|
||||
unsigned int i, eop, count = 0;
|
||||
bool cleaned = false;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (netmap_tx_irq(netdev, tx_ring->queue_index))
|
||||
+ return 1; /* cleaned ok */
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
i = tx_ring->next_to_clean;
|
||||
eop = tx_ring->buffer_info[i].next_to_watch;
|
||||
eop_desc = E1000_TX_DESC_ADV(*tx_ring, eop);
|
||||
@@ -5540,6 +5572,11 @@ static bool igb_clean_rx_irq_adv(struct igb_q_vector *q_vector,
|
||||
u16 length;
|
||||
u16 vlan_tag;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (netmap_rx_irq(netdev, rx_ring->queue_index, work_done))
|
||||
+ return 1;
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
i = rx_ring->next_to_clean;
|
||||
buffer_info = &rx_ring->buffer_info[i];
|
||||
rx_desc = E1000_RX_DESC_ADV(*rx_ring, i);
|
||||
@@ -5668,6 +5705,10 @@ void igb_alloc_rx_buffers_adv(struct igb_ring *rx_ring, int cleaned_count)
|
||||
unsigned int i;
|
||||
int bufsz;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (igb_netmap_configure_rx_ring(rx_ring))
|
||||
+ return;
|
||||
+#endif /* DEV_NETMAP */
|
||||
i = rx_ring->next_to_use;
|
||||
buffer_info = &rx_ring->buffer_info[i];
|
||||
|
136
netmap/LINUX/final-patches/diff--igb--30200--30300
Normal file
136
netmap/LINUX/final-patches/diff--igb--30200--30300
Normal file
@ -0,0 +1,136 @@
|
||||
diff --git a/igb/igb_main.c b/igb/igb_main.c
|
||||
index ced5444..fb7c766 100644
|
||||
--- a/igb/igb_main.c
|
||||
+++ b/igb/igb_main.c
|
||||
@@ -225,6 +225,10 @@ MODULE_DESCRIPTION("Intel(R) Gigabit Ethernet Network Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(DRV_VERSION);
|
||||
|
||||
+#if defined(CONFIG_NETMAP) || defined(CONFIG_NETMAP_MODULE)
|
||||
+#include <if_igb_netmap.h>
|
||||
+#endif
|
||||
+
|
||||
struct igb_reg_info {
|
||||
u32 ofs;
|
||||
char *name;
|
||||
@@ -1551,6 +1555,10 @@ int igb_up(struct igb_adapter *adapter)
|
||||
|
||||
netif_tx_start_all_queues(adapter->netdev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_enable_all_rings(adapter->netdev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
/* start the watchdog. */
|
||||
hw->mac.get_link_status = 1;
|
||||
schedule_work(&adapter->watchdog_task);
|
||||
@@ -1584,6 +1592,10 @@ void igb_down(struct igb_adapter *adapter)
|
||||
wrfl();
|
||||
msleep(10);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_disable_all_rings(netdev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
for (i = 0; i < adapter->num_q_vectors; i++)
|
||||
napi_disable(&(adapter->q_vector[i]->napi));
|
||||
|
||||
@@ -2073,6 +2085,10 @@ static int __devinit igb_probe(struct pci_dev *pdev,
|
||||
/* carrier off reporting is important to ethtool even BEFORE open */
|
||||
netif_carrier_off(netdev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ igb_netmap_attach(adapter);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
#ifdef CONFIG_IGB_DCA
|
||||
if (dca_add_requester(&pdev->dev) == 0) {
|
||||
adapter->flags |= IGB_FLAG_DCA_ENABLED;
|
||||
@@ -2199,6 +2215,10 @@ static void __devexit igb_remove(struct pci_dev *pdev)
|
||||
dev_info(&pdev->dev, "IOV Disabled\n");
|
||||
}
|
||||
#endif
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_detach(netdev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
|
||||
iounmap(hw->hw_addr);
|
||||
if (hw->flash_address)
|
||||
@@ -2529,6 +2549,10 @@ static int igb_open(struct net_device *netdev)
|
||||
|
||||
netif_tx_start_all_queues(netdev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_enable_all_rings(netdev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
/* start the watchdog. */
|
||||
hw->mac.get_link_status = 1;
|
||||
schedule_work(&adapter->watchdog_task);
|
||||
@@ -2711,6 +2735,9 @@ void igb_configure_tx_ring(struct igb_adapter *adapter,
|
||||
|
||||
txdctl |= E1000_TXDCTL_QUEUE_ENABLE;
|
||||
wr32(E1000_TXDCTL(reg_idx), txdctl);
|
||||
+#ifdef DEV_NETMAP
|
||||
+ igb_netmap_configure_tx_ring(adapter, reg_idx);
|
||||
+#endif /* DEV_NETMAP */
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3088,6 +3115,19 @@ void igb_configure_rx_ring(struct igb_adapter *adapter,
|
||||
/* Only set Drop Enable if we are supporting multiple queues */
|
||||
if (adapter->vfs_allocated_count || adapter->num_rx_queues > 1)
|
||||
srrctl |= E1000_SRRCTL_DROP_EN;
|
||||
+#ifdef DEV_NETMAP
|
||||
+ {
|
||||
+ /* The driver uses split buffers, which are not
|
||||
+ * supported in netmap mode */
|
||||
+ struct ifnet *ifp = adapter->netdev;
|
||||
+ struct netmap_adapter *na = NA(ifp);
|
||||
+ if (na && ifp->if_capenable & IFCAP_NETMAP) {
|
||||
+ srrctl &= ~(7 << 25); /* clear descriptor type */
|
||||
+ srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF;
|
||||
+ /* XXX we should set tail here */
|
||||
+ }
|
||||
+ }
|
||||
+#endif
|
||||
|
||||
wr32(E1000_SRRCTL(reg_idx), srrctl);
|
||||
|
||||
@@ -5705,6 +5745,10 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector)
|
||||
|
||||
if (test_bit(__IGB_DOWN, &adapter->state))
|
||||
return true;
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (netmap_tx_irq(tx_ring->netdev, tx_ring->queue_index))
|
||||
+ return 1; /* cleaned ok */
|
||||
+#endif /* DEV_NETMAP */
|
||||
|
||||
tx_buffer = &tx_ring->tx_buffer_info[i];
|
||||
tx_desc = IGB_TX_DESC(tx_ring, i);
|
||||
@@ -5980,6 +6024,12 @@ static bool igb_clean_rx_irq(struct igb_q_vector *q_vector, int budget)
|
||||
u16 cleaned_count = igb_desc_unused(rx_ring);
|
||||
u16 i = rx_ring->next_to_clean;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ int dummy = 1; // select rx irq handling
|
||||
+ if (netmap_rx_irq(rx_ring->netdev, rx_ring->queue_index, &dummy))
|
||||
+ return 1;
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
rx_desc = IGB_RX_DESC(rx_ring, i);
|
||||
|
||||
while (igb_test_staterr(rx_desc, E1000_RXD_STAT_DD)) {
|
||||
@@ -6170,6 +6220,11 @@ void igb_alloc_rx_buffers(struct igb_ring *rx_ring, u16 cleaned_count)
|
||||
struct igb_rx_buffer *bi;
|
||||
u16 i = rx_ring->next_to_use;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (igb_netmap_configure_rx_ring(rx_ring))
|
||||
+ return;
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
rx_desc = IGB_RX_DESC(rx_ring, i);
|
||||
bi = &rx_ring->rx_buffer_info[i];
|
||||
i -= rx_ring->count;
|
136
netmap/LINUX/final-patches/diff--igb--30300--30800
Normal file
136
netmap/LINUX/final-patches/diff--igb--30300--30800
Normal file
@ -0,0 +1,136 @@
|
||||
diff --git a/igb/igb_main.c b/igb/igb_main.c
|
||||
index 94be6c3..294051b 100644
|
||||
--- a/igb/igb_main.c
|
||||
+++ b/igb/igb_main.c
|
||||
@@ -236,6 +236,10 @@ MODULE_DESCRIPTION("Intel(R) Gigabit Ethernet Network Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(DRV_VERSION);
|
||||
|
||||
+#if defined(CONFIG_NETMAP) || defined(CONFIG_NETMAP_MODULE)
|
||||
+#include <if_igb_netmap.h>
|
||||
+#endif
|
||||
+
|
||||
struct igb_reg_info {
|
||||
u32 ofs;
|
||||
char *name;
|
||||
@@ -1557,6 +1561,10 @@ int igb_up(struct igb_adapter *adapter)
|
||||
|
||||
netif_tx_start_all_queues(adapter->netdev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_enable_all_rings(adapter->netdev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
/* start the watchdog. */
|
||||
hw->mac.get_link_status = 1;
|
||||
schedule_work(&adapter->watchdog_task);
|
||||
@@ -1590,6 +1598,10 @@ void igb_down(struct igb_adapter *adapter)
|
||||
wrfl();
|
||||
msleep(10);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_disable_all_rings(netdev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
for (i = 0; i < adapter->num_q_vectors; i++)
|
||||
napi_disable(&(adapter->q_vector[i]->napi));
|
||||
|
||||
@@ -2081,6 +2093,10 @@ static int __devinit igb_probe(struct pci_dev *pdev,
|
||||
/* carrier off reporting is important to ethtool even BEFORE open */
|
||||
netif_carrier_off(netdev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ igb_netmap_attach(adapter);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
#ifdef CONFIG_IGB_DCA
|
||||
if (dca_add_requester(&pdev->dev) == 0) {
|
||||
adapter->flags |= IGB_FLAG_DCA_ENABLED;
|
||||
@@ -2211,6 +2227,10 @@ static void __devexit igb_remove(struct pci_dev *pdev)
|
||||
dev_info(&pdev->dev, "IOV Disabled\n");
|
||||
}
|
||||
#endif
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_detach(netdev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
|
||||
iounmap(hw->hw_addr);
|
||||
if (hw->flash_address)
|
||||
@@ -2547,6 +2567,10 @@ static int __igb_open(struct net_device *netdev, bool resuming)
|
||||
|
||||
netif_tx_start_all_queues(netdev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_enable_all_rings(netdev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
if (!resuming)
|
||||
pm_runtime_put(&pdev->dev);
|
||||
|
||||
@@ -2750,6 +2774,9 @@ void igb_configure_tx_ring(struct igb_adapter *adapter,
|
||||
|
||||
txdctl |= E1000_TXDCTL_QUEUE_ENABLE;
|
||||
wr32(E1000_TXDCTL(reg_idx), txdctl);
|
||||
+#ifdef DEV_NETMAP
|
||||
+ igb_netmap_configure_tx_ring(adapter, reg_idx);
|
||||
+#endif /* DEV_NETMAP */
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3127,6 +3154,19 @@ void igb_configure_rx_ring(struct igb_adapter *adapter,
|
||||
/* Only set Drop Enable if we are supporting multiple queues */
|
||||
if (adapter->vfs_allocated_count || adapter->num_rx_queues > 1)
|
||||
srrctl |= E1000_SRRCTL_DROP_EN;
|
||||
+#ifdef DEV_NETMAP
|
||||
+ {
|
||||
+ /* The driver uses split buffers, which are not
|
||||
+ * supported in netmap mode */
|
||||
+ struct ifnet *ifp = adapter->netdev;
|
||||
+ struct netmap_adapter *na = NA(ifp);
|
||||
+ if (na && ifp->if_capenable & IFCAP_NETMAP) {
|
||||
+ srrctl &= ~(7 << 25); /* clear descriptor type */
|
||||
+ srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF;
|
||||
+ /* XXX we should set tail here */
|
||||
+ }
|
||||
+ }
|
||||
+#endif
|
||||
|
||||
wr32(E1000_SRRCTL(reg_idx), srrctl);
|
||||
|
||||
@@ -5753,6 +5793,10 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector)
|
||||
|
||||
if (test_bit(__IGB_DOWN, &adapter->state))
|
||||
return true;
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (netmap_tx_irq(tx_ring->netdev, tx_ring->queue_index))
|
||||
+ return 1; /* cleaned ok */
|
||||
+#endif /* DEV_NETMAP */
|
||||
|
||||
tx_buffer = &tx_ring->tx_buffer_info[i];
|
||||
tx_desc = IGB_TX_DESC(tx_ring, i);
|
||||
@@ -6030,6 +6074,12 @@ static bool igb_clean_rx_irq(struct igb_q_vector *q_vector, int budget)
|
||||
u16 cleaned_count = igb_desc_unused(rx_ring);
|
||||
u16 i = rx_ring->next_to_clean;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ int dummy = 1; // select rx irq handling
|
||||
+ if (netmap_rx_irq(rx_ring->netdev, rx_ring->queue_index, &dummy))
|
||||
+ return 1;
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
rx_desc = IGB_RX_DESC(rx_ring, i);
|
||||
|
||||
while (igb_test_staterr(rx_desc, E1000_RXD_STAT_DD)) {
|
||||
@@ -6220,6 +6270,11 @@ void igb_alloc_rx_buffers(struct igb_ring *rx_ring, u16 cleaned_count)
|
||||
struct igb_rx_buffer *bi;
|
||||
u16 i = rx_ring->next_to_use;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (igb_netmap_configure_rx_ring(rx_ring))
|
||||
+ return;
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
rx_desc = IGB_RX_DESC(rx_ring, i);
|
||||
bi = &rx_ring->rx_buffer_info[i];
|
||||
i -= rx_ring->count;
|
114
netmap/LINUX/final-patches/diff--igb--30800--30b00
Normal file
114
netmap/LINUX/final-patches/diff--igb--30800--30b00
Normal file
@ -0,0 +1,114 @@
|
||||
diff --git a/igb/igb_main.c b/igb/igb_main.c
|
||||
index 31cfe2e..8439bc6 100644
|
||||
--- a/igb/igb_main.c
|
||||
+++ b/igb/igb_main.c
|
||||
@@ -247,6 +247,10 @@ static int debug = -1;
|
||||
module_param(debug, int, 0);
|
||||
MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
|
||||
|
||||
+#if defined(CONFIG_NETMAP) || defined(CONFIG_NETMAP_MODULE)
|
||||
+#include <if_igb_netmap.h>
|
||||
+#endif
|
||||
+
|
||||
struct igb_reg_info {
|
||||
u32 ofs;
|
||||
char *name;
|
||||
@@ -1520,6 +1524,10 @@ int igb_up(struct igb_adapter *adapter)
|
||||
|
||||
netif_tx_start_all_queues(adapter->netdev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_enable_all_rings(adapter->netdev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
/* start the watchdog. */
|
||||
hw->mac.get_link_status = 1;
|
||||
schedule_work(&adapter->watchdog_task);
|
||||
@@ -1553,6 +1561,10 @@ void igb_down(struct igb_adapter *adapter)
|
||||
wrfl();
|
||||
msleep(10);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_disable_all_rings(netdev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
for (i = 0; i < adapter->num_q_vectors; i++)
|
||||
napi_disable(&(adapter->q_vector[i]->napi));
|
||||
|
||||
@@ -2127,6 +2139,10 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
/* carrier off reporting is important to ethtool even BEFORE open */
|
||||
netif_carrier_off(netdev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ igb_netmap_attach(adapter);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
#ifdef CONFIG_IGB_DCA
|
||||
if (dca_add_requester(&pdev->dev) == 0) {
|
||||
adapter->flags |= IGB_FLAG_DCA_ENABLED;
|
||||
@@ -2233,6 +2249,10 @@ static void igb_remove(struct pci_dev *pdev)
|
||||
wr32(E1000_DCA_CTRL, E1000_DCA_CTRL_DCA_MODE_DISABLE);
|
||||
}
|
||||
#endif
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_detach(netdev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
|
||||
/* Release control of h/w to f/w. If f/w is AMT enabled, this
|
||||
* would have already happened in close and is redundant. */
|
||||
@@ -2553,6 +2573,10 @@ static int __igb_open(struct net_device *netdev, bool resuming)
|
||||
|
||||
netif_tx_start_all_queues(netdev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_enable_all_rings(netdev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
if (!resuming)
|
||||
pm_runtime_put(&pdev->dev);
|
||||
|
||||
@@ -2746,6 +2770,9 @@ void igb_configure_tx_ring(struct igb_adapter *adapter,
|
||||
|
||||
txdctl |= E1000_TXDCTL_QUEUE_ENABLE;
|
||||
wr32(E1000_TXDCTL(reg_idx), txdctl);
|
||||
+#ifdef DEV_NETMAP
|
||||
+ igb_netmap_configure_tx_ring(adapter, reg_idx);
|
||||
+#endif /* DEV_NETMAP */
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -5690,6 +5717,10 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector)
|
||||
|
||||
if (test_bit(__IGB_DOWN, &adapter->state))
|
||||
return true;
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (netmap_tx_irq(tx_ring->netdev, tx_ring->queue_index))
|
||||
+ return 1; /* cleaned ok */
|
||||
+#endif /* DEV_NETMAP */
|
||||
|
||||
tx_buffer = &tx_ring->tx_buffer_info[i];
|
||||
tx_desc = IGB_TX_DESC(tx_ring, i);
|
||||
@@ -6349,6 +6380,10 @@ static bool igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget)
|
||||
unsigned int total_bytes = 0, total_packets = 0;
|
||||
u16 cleaned_count = igb_desc_unused(rx_ring);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (netmap_rx_irq(rx_ring->netdev, rx_ring->queue_index, &total_packets))
|
||||
+ return true;
|
||||
+#endif /* DEV_NETMAP */
|
||||
do {
|
||||
union e1000_adv_rx_desc *rx_desc;
|
||||
|
||||
@@ -6461,6 +6496,11 @@ void igb_alloc_rx_buffers(struct igb_ring *rx_ring, u16 cleaned_count)
|
||||
struct igb_rx_buffer *bi;
|
||||
u16 i = rx_ring->next_to_use;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (igb_netmap_configure_rx_ring(rx_ring))
|
||||
+ return;
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
/* nothing to do */
|
||||
if (!cleaned_count)
|
||||
return;
|
113
netmap/LINUX/final-patches/diff--igb--30b00--99999
Normal file
113
netmap/LINUX/final-patches/diff--igb--30b00--99999
Normal file
@ -0,0 +1,113 @@
|
||||
diff --git a/igb/igb_main.c b/igb/igb_main.c
|
||||
index c1d72c0..9815796 100644
|
||||
--- a/igb/igb_main.c
|
||||
+++ b/igb/igb_main.c
|
||||
@@ -255,6 +255,10 @@ static int debug = -1;
|
||||
module_param(debug, int, 0);
|
||||
MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
|
||||
|
||||
+#if defined(CONFIG_NETMAP) || defined(CONFIG_NETMAP_MODULE)
|
||||
+#include <if_igb_netmap.h>
|
||||
+#endif
|
||||
+
|
||||
struct igb_reg_info {
|
||||
u32 ofs;
|
||||
char *name;
|
||||
@@ -1633,6 +1637,10 @@ int igb_up(struct igb_adapter *adapter)
|
||||
|
||||
netif_tx_start_all_queues(adapter->netdev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_enable_all_rings(adapter->netdev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
/* start the watchdog. */
|
||||
hw->mac.get_link_status = 1;
|
||||
schedule_work(&adapter->watchdog_task);
|
||||
@@ -1674,6 +1682,9 @@ void igb_down(struct igb_adapter *adapter)
|
||||
napi_disable(&(adapter->q_vector[i]->napi));
|
||||
}
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_disable_all_rings(netdev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
|
||||
del_timer_sync(&adapter->watchdog_timer);
|
||||
del_timer_sync(&adapter->phy_info_timer);
|
||||
@@ -2295,6 +2306,10 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
/* carrier off reporting is important to ethtool even BEFORE open */
|
||||
netif_carrier_off(netdev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ igb_netmap_attach(adapter);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
#ifdef CONFIG_IGB_DCA
|
||||
if (dca_add_requester(&pdev->dev) == 0) {
|
||||
adapter->flags |= IGB_FLAG_DCA_ENABLED;
|
||||
@@ -2536,6 +2551,10 @@ static void igb_remove(struct pci_dev *pdev)
|
||||
wr32(E1000_DCA_CTRL, E1000_DCA_CTRL_DCA_MODE_DISABLE);
|
||||
}
|
||||
#endif
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_detach(netdev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
|
||||
/* Release control of h/w to f/w. If f/w is AMT enabled, this
|
||||
* would have already happened in close and is redundant.
|
||||
@@ -2814,6 +2833,10 @@ static int __igb_open(struct net_device *netdev, bool resuming)
|
||||
|
||||
netif_tx_start_all_queues(netdev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_enable_all_rings(netdev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
if (!resuming)
|
||||
pm_runtime_put(&pdev->dev);
|
||||
|
||||
@@ -3007,6 +3030,9 @@ void igb_configure_tx_ring(struct igb_adapter *adapter,
|
||||
|
||||
txdctl |= E1000_TXDCTL_QUEUE_ENABLE;
|
||||
wr32(E1000_TXDCTL(reg_idx), txdctl);
|
||||
+#ifdef DEV_NETMAP
|
||||
+ igb_netmap_configure_tx_ring(adapter, reg_idx);
|
||||
+#endif /* DEV_NETMAP */
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -5991,6 +6017,10 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector)
|
||||
|
||||
if (test_bit(__IGB_DOWN, &adapter->state))
|
||||
return true;
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (netmap_tx_irq(tx_ring->netdev, tx_ring->queue_index))
|
||||
+ return 1; /* cleaned ok */
|
||||
+#endif /* DEV_NETMAP */
|
||||
|
||||
tx_buffer = &tx_ring->tx_buffer_info[i];
|
||||
tx_desc = IGB_TX_DESC(tx_ring, i);
|
||||
@@ -6650,6 +6680,10 @@ static bool igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget)
|
||||
unsigned int total_bytes = 0, total_packets = 0;
|
||||
u16 cleaned_count = igb_desc_unused(rx_ring);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (netmap_rx_irq(rx_ring->netdev, rx_ring->queue_index, &total_packets))
|
||||
+ return true;
|
||||
+#endif /* DEV_NETMAP */
|
||||
do {
|
||||
union e1000_adv_rx_desc *rx_desc;
|
||||
|
||||
@@ -6767,6 +6801,11 @@ void igb_alloc_rx_buffers(struct igb_ring *rx_ring, u16 cleaned_count)
|
||||
struct igb_rx_buffer *bi;
|
||||
u16 i = rx_ring->next_to_use;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (igb_netmap_configure_rx_ring(rx_ring))
|
||||
+ return;
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
/* nothing to do */
|
||||
if (!cleaned_count)
|
||||
return;
|
113
netmap/LINUX/final-patches/diff--ixgbe--20625--20626
Normal file
113
netmap/LINUX/final-patches/diff--ixgbe--20625--20626
Normal file
@ -0,0 +1,113 @@
|
||||
diff --git a/ixgbe/ixgbe_main.c b/ixgbe/ixgbe_main.c
|
||||
index eee0b29..70581eb 100644
|
||||
--- a/ixgbe/ixgbe_main.c
|
||||
+++ b/ixgbe/ixgbe_main.c
|
||||
@@ -214,6 +214,22 @@ static const struct ixgbe_reg_info ixgbe_reg_info_tbl[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
+#if defined(CONFIG_NETMAP) || defined(CONFIG_NETMAP_MODULE)
|
||||
+/*
|
||||
+ * The #ifdef DEV_NETMAP / #endif blocks in this file are meant to
|
||||
+ * be a reference on how to implement netmap support in a driver.
|
||||
+ * Additional comments are in ixgbe_netmap_linux.h .
|
||||
+ *
|
||||
+ * The code is originally developed on FreeBSD and in the interest
|
||||
+ * of maintainability we try to limit differences between the two systems.
|
||||
+ *
|
||||
+ * <ixgbe_netmap_linux.h> contains functions for netmap support
|
||||
+ * that extend the standard driver.
|
||||
+ * It also defines DEV_NETMAP so further conditional sections use
|
||||
+ * that instead of CONFIG_NETMAP
|
||||
+ */
|
||||
+#include <ixgbe_netmap_linux.h>
|
||||
+#endif
|
||||
|
||||
/*
|
||||
* ixgbe_regdump - register printout routine
|
||||
@@ -740,6 +756,16 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
|
||||
unsigned int i, eop, count = 0;
|
||||
unsigned int total_bytes = 0, total_packets = 0;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ /*
|
||||
+ * In netmap mode, all the work is done in the context
|
||||
+ * of the client thread. Interrupt handlers only wake up
|
||||
+ * clients, which may be sleeping on individual rings
|
||||
+ * or on a global resource for all rings.
|
||||
+ */
|
||||
+ if (netmap_tx_irq(adapter->netdev, tx_ring->queue_index))
|
||||
+ return 1; /* seems to be ignored */
|
||||
+#endif /* DEV_NETMAP */
|
||||
i = tx_ring->next_to_clean;
|
||||
eop = tx_ring->tx_buffer_info[i].next_to_watch;
|
||||
eop_desc = IXGBE_TX_DESC_ADV(tx_ring, eop);
|
||||
@@ -1185,6 +1211,13 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
|
||||
int ddp_bytes = 0;
|
||||
#endif /* IXGBE_FCOE */
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ /*
|
||||
+ * Same as the txeof routine: only wakeup clients on intr.
|
||||
+ */
|
||||
+ if (netmap_rx_irq(adapter->netdev, rx_ring->queue_index, work_done))
|
||||
+ return;
|
||||
+#endif /* DEV_NETMAP */
|
||||
i = rx_ring->next_to_clean;
|
||||
rx_desc = IXGBE_RX_DESC_ADV(rx_ring, i);
|
||||
staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
|
||||
@@ -2519,6 +2552,9 @@ void ixgbe_configure_tx_ring(struct ixgbe_adapter *adapter,
|
||||
} while (--wait_loop && !(txdctl & IXGBE_TXDCTL_ENABLE));
|
||||
if (!wait_loop)
|
||||
e_err(drv, "Could not enable Tx Queue %d\n", reg_idx);
|
||||
+#ifdef DEV_NETMAP
|
||||
+ ixgbe_netmap_configure_tx_ring(adapter, reg_idx);
|
||||
+#endif /* DEV_NETMAP */
|
||||
}
|
||||
|
||||
static void ixgbe_setup_mtqc(struct ixgbe_adapter *adapter)
|
||||
@@ -2833,6 +2869,10 @@ void ixgbe_configure_rx_ring(struct ixgbe_adapter *adapter,
|
||||
IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(reg_idx), rxdctl);
|
||||
|
||||
ixgbe_rx_desc_queue_enable(adapter, ring);
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (ixgbe_netmap_configure_rx_ring(adapter, reg_idx))
|
||||
+ return;
|
||||
+#endif /* DEV_NETMAP */
|
||||
ixgbe_alloc_rx_buffers(adapter, ring, IXGBE_DESC_UNUSED(ring));
|
||||
}
|
||||
|
||||
@@ -3614,6 +3654,10 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
|
||||
/* enable transmits */
|
||||
netif_tx_start_all_queues(adapter->netdev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_enable_all_rings(adapter->netdev);
|
||||
+#endif
|
||||
+
|
||||
/* bring the link up in the watchdog, this could race with our first
|
||||
* link up interrupt but shouldn't be a problem */
|
||||
adapter->flags |= IXGBE_FLAG_NEED_LINK_UPDATE;
|
||||
@@ -3863,6 +3907,10 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
|
||||
|
||||
ixgbe_napi_disable_all(adapter);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_disable_all_rings(netdev);
|
||||
+#endif
|
||||
+
|
||||
/* Cleanup the affinity_hint CPU mask memory and callback */
|
||||
for (i = 0; i < num_q_vectors; i++) {
|
||||
struct ixgbe_q_vector *q_vector = adapter->q_vector[i];
|
||||
@@ -7048,6 +7096,11 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
|
||||
|
||||
e_dev_info("Intel(R) 10 Gigabit Network Connection\n");
|
||||
cards_found++;
|
||||
+
|
||||
+#ifdef DEV_NETMAP
|
||||
+ ixgbe_netmap_attach(adapter);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
return 0;
|
||||
|
||||
err_register:
|
113
netmap/LINUX/final-patches/diff--ixgbe--20626--30000
Normal file
113
netmap/LINUX/final-patches/diff--ixgbe--20626--30000
Normal file
@ -0,0 +1,113 @@
|
||||
diff --git a/ixgbe/ixgbe_main.c b/ixgbe/ixgbe_main.c
|
||||
index 30f9ccf..60c0252 100644
|
||||
--- a/ixgbe/ixgbe_main.c
|
||||
+++ b/ixgbe/ixgbe_main.c
|
||||
@@ -221,6 +221,22 @@ static const struct ixgbe_reg_info ixgbe_reg_info_tbl[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
+#if defined(CONFIG_NETMAP) || defined(CONFIG_NETMAP_MODULE)
|
||||
+/*
|
||||
+ * The #ifdef DEV_NETMAP / #endif blocks in this file are meant to
|
||||
+ * be a reference on how to implement netmap support in a driver.
|
||||
+ * Additional comments are in ixgbe_netmap_linux.h .
|
||||
+ *
|
||||
+ * The code is originally developed on FreeBSD and in the interest
|
||||
+ * of maintainability we try to limit differences between the two systems.
|
||||
+ *
|
||||
+ * <ixgbe_netmap_linux.h> contains functions for netmap support
|
||||
+ * that extend the standard driver.
|
||||
+ * It also defines DEV_NETMAP so further conditional sections use
|
||||
+ * that instead of CONFIG_NETMAP
|
||||
+ */
|
||||
+#include <ixgbe_netmap_linux.h>
|
||||
+#endif
|
||||
|
||||
/*
|
||||
* ixgbe_regdump - register printout routine
|
||||
@@ -826,6 +842,16 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
|
||||
unsigned int total_bytes = 0, total_packets = 0;
|
||||
u16 i, eop, count = 0;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ /*
|
||||
+ * In netmap mode, all the work is done in the context
|
||||
+ * of the client thread. Interrupt handlers only wake up
|
||||
+ * clients, which may be sleeping on individual rings
|
||||
+ * or on a global resource for all rings.
|
||||
+ */
|
||||
+ if (netmap_tx_irq(adapter->netdev, tx_ring->queue_index))
|
||||
+ return 1; /* seems to be ignored */
|
||||
+#endif /* DEV_NETMAP */
|
||||
i = tx_ring->next_to_clean;
|
||||
eop = tx_ring->tx_buffer_info[i].next_to_watch;
|
||||
eop_desc = IXGBE_TX_DESC_ADV(tx_ring, eop);
|
||||
@@ -1308,6 +1334,13 @@ static void ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
|
||||
u16 cleaned_count = 0;
|
||||
bool pkt_is_rsc = false;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ /*
|
||||
+ * Same as the txeof routine: only wakeup clients on intr.
|
||||
+ */
|
||||
+ if (netmap_rx_irq(adapter->netdev, rx_ring->queue_index, work_done))
|
||||
+ return;
|
||||
+#endif /* DEV_NETMAP */
|
||||
i = rx_ring->next_to_clean;
|
||||
rx_desc = IXGBE_RX_DESC_ADV(rx_ring, i);
|
||||
staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
|
||||
@@ -2730,6 +2763,9 @@ void ixgbe_configure_tx_ring(struct ixgbe_adapter *adapter,
|
||||
} while (--wait_loop && !(txdctl & IXGBE_TXDCTL_ENABLE));
|
||||
if (!wait_loop)
|
||||
e_err(drv, "Could not enable Tx Queue %d\n", reg_idx);
|
||||
+#ifdef DEV_NETMAP
|
||||
+ ixgbe_netmap_configure_tx_ring(adapter, reg_idx);
|
||||
+#endif /* DEV_NETMAP */
|
||||
}
|
||||
|
||||
static void ixgbe_setup_mtqc(struct ixgbe_adapter *adapter)
|
||||
@@ -3094,6 +3130,10 @@ void ixgbe_configure_rx_ring(struct ixgbe_adapter *adapter,
|
||||
IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(reg_idx), rxdctl);
|
||||
|
||||
ixgbe_rx_desc_queue_enable(adapter, ring);
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (ixgbe_netmap_configure_rx_ring(adapter, reg_idx))
|
||||
+ return;
|
||||
+#endif /* DEV_NETMAP */
|
||||
ixgbe_alloc_rx_buffers(ring, IXGBE_DESC_UNUSED(ring));
|
||||
}
|
||||
|
||||
@@ -3882,6 +3922,10 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
|
||||
/* enable transmits */
|
||||
netif_tx_start_all_queues(adapter->netdev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_enable_all_rings(adapter->netdev);
|
||||
+#endif
|
||||
+
|
||||
/* bring the link up in the watchdog, this could race with our first
|
||||
* link up interrupt but shouldn't be a problem */
|
||||
adapter->flags |= IXGBE_FLAG_NEED_LINK_UPDATE;
|
||||
@@ -4121,6 +4165,10 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
|
||||
|
||||
ixgbe_napi_disable_all(adapter);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_disable_all_rings(netdev);
|
||||
+#endif
|
||||
+
|
||||
/* Cleanup the affinity_hint CPU mask memory and callback */
|
||||
for (i = 0; i < num_q_vectors; i++) {
|
||||
struct ixgbe_q_vector *q_vector = adapter->q_vector[i];
|
||||
@@ -7450,6 +7498,11 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
|
||||
|
||||
e_dev_info("Intel(R) 10 Gigabit Network Connection\n");
|
||||
cards_found++;
|
||||
+
|
||||
+#ifdef DEV_NETMAP
|
||||
+ ixgbe_netmap_attach(adapter);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
return 0;
|
||||
|
||||
err_register:
|
113
netmap/LINUX/final-patches/diff--ixgbe--30000--30100
Normal file
113
netmap/LINUX/final-patches/diff--ixgbe--30000--30100
Normal file
@ -0,0 +1,113 @@
|
||||
diff --git a/ixgbe/ixgbe_main.c b/ixgbe/ixgbe_main.c
|
||||
index 08e8e25..8070930 100644
|
||||
--- a/ixgbe/ixgbe_main.c
|
||||
+++ b/ixgbe/ixgbe_main.c
|
||||
@@ -247,6 +247,22 @@ static const struct ixgbe_reg_info ixgbe_reg_info_tbl[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
+#if defined(CONFIG_NETMAP) || defined(CONFIG_NETMAP_MODULE)
|
||||
+/*
|
||||
+ * The #ifdef DEV_NETMAP / #endif blocks in this file are meant to
|
||||
+ * be a reference on how to implement netmap support in a driver.
|
||||
+ * Additional comments are in ixgbe_netmap_linux.h .
|
||||
+ *
|
||||
+ * The code is originally developed on FreeBSD and in the interest
|
||||
+ * of maintainability we try to limit differences between the two systems.
|
||||
+ *
|
||||
+ * <ixgbe_netmap_linux.h> contains functions for netmap support
|
||||
+ * that extend the standard driver.
|
||||
+ * It also defines DEV_NETMAP so further conditional sections use
|
||||
+ * that instead of CONFIG_NETMAP
|
||||
+ */
|
||||
+#include <ixgbe_netmap_linux.h>
|
||||
+#endif
|
||||
|
||||
/*
|
||||
* ixgbe_regdump - register printout routine
|
||||
@@ -864,6 +880,16 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
|
||||
unsigned int total_bytes = 0, total_packets = 0;
|
||||
u16 i, eop, count = 0;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ /*
|
||||
+ * In netmap mode, all the work is done in the context
|
||||
+ * of the client thread. Interrupt handlers only wake up
|
||||
+ * clients, which may be sleeping on individual rings
|
||||
+ * or on a global resource for all rings.
|
||||
+ */
|
||||
+ if (netmap_tx_irq(adapter->netdev, tx_ring->queue_index))
|
||||
+ return 1; /* seems to be ignored */
|
||||
+#endif /* DEV_NETMAP */
|
||||
i = tx_ring->next_to_clean;
|
||||
eop = tx_ring->tx_buffer_info[i].next_to_watch;
|
||||
eop_desc = IXGBE_TX_DESC_ADV(tx_ring, eop);
|
||||
@@ -1348,6 +1374,13 @@ static void ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
|
||||
u16 cleaned_count = 0;
|
||||
bool pkt_is_rsc = false;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ /*
|
||||
+ * Same as the txeof routine: only wakeup clients on intr.
|
||||
+ */
|
||||
+ if (netmap_rx_irq(adapter->netdev, rx_ring->queue_index, work_done))
|
||||
+ return;
|
||||
+#endif /* DEV_NETMAP */
|
||||
i = rx_ring->next_to_clean;
|
||||
rx_desc = IXGBE_RX_DESC_ADV(rx_ring, i);
|
||||
staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
|
||||
@@ -2808,6 +2841,9 @@ void ixgbe_configure_tx_ring(struct ixgbe_adapter *adapter,
|
||||
} while (--wait_loop && !(txdctl & IXGBE_TXDCTL_ENABLE));
|
||||
if (!wait_loop)
|
||||
e_err(drv, "Could not enable Tx Queue %d\n", reg_idx);
|
||||
+#ifdef DEV_NETMAP
|
||||
+ ixgbe_netmap_configure_tx_ring(adapter, reg_idx);
|
||||
+#endif /* DEV_NETMAP */
|
||||
}
|
||||
|
||||
static void ixgbe_setup_mtqc(struct ixgbe_adapter *adapter)
|
||||
@@ -3183,6 +3219,10 @@ void ixgbe_configure_rx_ring(struct ixgbe_adapter *adapter,
|
||||
IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(reg_idx), rxdctl);
|
||||
|
||||
ixgbe_rx_desc_queue_enable(adapter, ring);
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (ixgbe_netmap_configure_rx_ring(adapter, reg_idx))
|
||||
+ return;
|
||||
+#endif /* DEV_NETMAP */
|
||||
ixgbe_alloc_rx_buffers(ring, IXGBE_DESC_UNUSED(ring));
|
||||
}
|
||||
|
||||
@@ -3976,6 +4016,10 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
|
||||
/* enable transmits */
|
||||
netif_tx_start_all_queues(adapter->netdev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_enable_all_rings(adapter->netdev);
|
||||
+#endif
|
||||
+
|
||||
/* bring the link up in the watchdog, this could race with our first
|
||||
* link up interrupt but shouldn't be a problem */
|
||||
adapter->flags |= IXGBE_FLAG_NEED_LINK_UPDATE;
|
||||
@@ -4212,6 +4256,10 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
|
||||
|
||||
ixgbe_napi_disable_all(adapter);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_disable_all_rings(netdev);
|
||||
+#endif
|
||||
+
|
||||
adapter->flags2 &= ~(IXGBE_FLAG2_FDIR_REQUIRES_REINIT |
|
||||
IXGBE_FLAG2_RESET_REQUESTED);
|
||||
adapter->flags &= ~IXGBE_FLAG_NEED_LINK_UPDATE;
|
||||
@@ -7683,6 +7731,11 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
|
||||
|
||||
e_dev_info("Intel(R) 10 Gigabit Network Connection\n");
|
||||
cards_found++;
|
||||
+
|
||||
+#ifdef DEV_NETMAP
|
||||
+ ixgbe_netmap_attach(adapter);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
return 0;
|
||||
|
||||
err_register:
|
114
netmap/LINUX/final-patches/diff--ixgbe--30100--30200
Normal file
114
netmap/LINUX/final-patches/diff--ixgbe--30100--30200
Normal file
@ -0,0 +1,114 @@
|
||||
diff --git a/ixgbe/ixgbe_main.c b/ixgbe/ixgbe_main.c
|
||||
index e1fcc95..1aab0df 100644
|
||||
--- a/ixgbe/ixgbe_main.c
|
||||
+++ b/ixgbe/ixgbe_main.c
|
||||
@@ -249,6 +249,22 @@ static const struct ixgbe_reg_info ixgbe_reg_info_tbl[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
+#if defined(CONFIG_NETMAP) || defined(CONFIG_NETMAP_MODULE)
|
||||
+/*
|
||||
+ * The #ifdef DEV_NETMAP / #endif blocks in this file are meant to
|
||||
+ * be a reference on how to implement netmap support in a driver.
|
||||
+ * Additional comments are in ixgbe_netmap_linux.h .
|
||||
+ *
|
||||
+ * The code is originally developed on FreeBSD and in the interest
|
||||
+ * of maintainability we try to limit differences between the two systems.
|
||||
+ *
|
||||
+ * <ixgbe_netmap_linux.h> contains functions for netmap support
|
||||
+ * that extend the standard driver.
|
||||
+ * It also defines DEV_NETMAP so further conditional sections use
|
||||
+ * that instead of CONFIG_NETMAP
|
||||
+ */
|
||||
+#include <ixgbe_netmap_linux.h>
|
||||
+#endif
|
||||
|
||||
/*
|
||||
* ixgbe_regdump - register printout routine
|
||||
@@ -801,6 +817,17 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
|
||||
unsigned int total_bytes = 0, total_packets = 0;
|
||||
u16 i, eop, count = 0;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ /*
|
||||
+ * In netmap mode, all the work is done in the context
|
||||
+ * of the client thread. Interrupt handlers only wake up
|
||||
+ * clients, which may be sleeping on individual rings
|
||||
+ * or on a global resource for all rings.
|
||||
+ */
|
||||
+ if (netmap_tx_irq(adapter->netdev, tx_ring->queue_index))
|
||||
+ return 1; /* seems to be ignored */
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
i = tx_ring->next_to_clean;
|
||||
eop = tx_ring->tx_buffer_info[i].next_to_watch;
|
||||
eop_desc = IXGBE_TX_DESC_ADV(tx_ring, eop);
|
||||
@@ -1303,6 +1330,13 @@ static void ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
|
||||
u16 cleaned_count = 0;
|
||||
bool pkt_is_rsc = false;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ /*
|
||||
+ * Same as the txeof routine: only wakeup clients on intr.
|
||||
+ */
|
||||
+ if (netmap_rx_irq(adapter->netdev, rx_ring->queue_index, work_done))
|
||||
+ return;
|
||||
+#endif /* DEV_NETMAP */
|
||||
i = rx_ring->next_to_clean;
|
||||
rx_desc = IXGBE_RX_DESC_ADV(rx_ring, i);
|
||||
staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
|
||||
@@ -2676,6 +2710,9 @@ void ixgbe_configure_tx_ring(struct ixgbe_adapter *adapter,
|
||||
} while (--wait_loop && !(txdctl & IXGBE_TXDCTL_ENABLE));
|
||||
if (!wait_loop)
|
||||
e_err(drv, "Could not enable Tx Queue %d\n", reg_idx);
|
||||
+#ifdef DEV_NETMAP
|
||||
+ ixgbe_netmap_configure_tx_ring(adapter, reg_idx);
|
||||
+#endif /* DEV_NETMAP */
|
||||
}
|
||||
|
||||
static void ixgbe_setup_mtqc(struct ixgbe_adapter *adapter)
|
||||
@@ -3039,6 +3076,10 @@ void ixgbe_configure_rx_ring(struct ixgbe_adapter *adapter,
|
||||
IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(reg_idx), rxdctl);
|
||||
|
||||
ixgbe_rx_desc_queue_enable(adapter, ring);
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (ixgbe_netmap_configure_rx_ring(adapter, reg_idx))
|
||||
+ return;
|
||||
+#endif /* DEV_NETMAP */
|
||||
ixgbe_alloc_rx_buffers(ring, ixgbe_desc_unused(ring));
|
||||
}
|
||||
|
||||
@@ -3873,6 +3914,10 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
|
||||
/* enable transmits */
|
||||
netif_tx_start_all_queues(adapter->netdev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_enable_all_rings(adapter->netdev);
|
||||
+#endif
|
||||
+
|
||||
/* bring the link up in the watchdog, this could race with our first
|
||||
* link up interrupt but shouldn't be a problem */
|
||||
adapter->flags |= IXGBE_FLAG_NEED_LINK_UPDATE;
|
||||
@@ -4126,6 +4171,10 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
|
||||
|
||||
ixgbe_napi_disable_all(adapter);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_disable_all_rings(netdev);
|
||||
+#endif
|
||||
+
|
||||
adapter->flags2 &= ~(IXGBE_FLAG2_FDIR_REQUIRES_REINIT |
|
||||
IXGBE_FLAG2_RESET_REQUESTED);
|
||||
adapter->flags &= ~IXGBE_FLAG_NEED_LINK_UPDATE;
|
||||
@@ -7696,6 +7745,11 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
|
||||
|
||||
e_dev_info("Intel(R) 10 Gigabit Network Connection\n");
|
||||
cards_found++;
|
||||
+
|
||||
+#ifdef DEV_NETMAP
|
||||
+ ixgbe_netmap_attach(adapter);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
return 0;
|
||||
|
||||
err_register:
|
115
netmap/LINUX/final-patches/diff--ixgbe--30200--30400
Normal file
115
netmap/LINUX/final-patches/diff--ixgbe--30200--30400
Normal file
@ -0,0 +1,115 @@
|
||||
diff --git a/ixgbe/ixgbe_main.c b/ixgbe/ixgbe_main.c
|
||||
index 8ef92d1..6a37803 100644
|
||||
--- a/ixgbe/ixgbe_main.c
|
||||
+++ b/ixgbe/ixgbe_main.c
|
||||
@@ -188,6 +188,22 @@ static const struct ixgbe_reg_info ixgbe_reg_info_tbl[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
+#if defined(CONFIG_NETMAP) || defined(CONFIG_NETMAP_MODULE)
|
||||
+/*
|
||||
+ * The #ifdef DEV_NETMAP / #endif blocks in this file are meant to
|
||||
+ * be a reference on how to implement netmap support in a driver.
|
||||
+ * Additional comments are in ixgbe_netmap_linux.h .
|
||||
+ *
|
||||
+ * The code is originally developed on FreeBSD and in the interest
|
||||
+ * of maintainability we try to limit differences between the two systems.
|
||||
+ *
|
||||
+ * <ixgbe_netmap_linux.h> contains functions for netmap support
|
||||
+ * that extend the standard driver.
|
||||
+ * It also defines DEV_NETMAP so further conditional sections use
|
||||
+ * that instead of CONFIG_NETMAP
|
||||
+ */
|
||||
+#include <ixgbe_netmap_linux.h>
|
||||
+#endif
|
||||
|
||||
/*
|
||||
* ixgbe_regdump - register printout routine
|
||||
@@ -745,6 +761,17 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
|
||||
unsigned int budget = q_vector->tx.work_limit;
|
||||
u16 i = tx_ring->next_to_clean;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ /*
|
||||
+ * In netmap mode, all the work is done in the context
|
||||
+ * of the client thread. Interrupt handlers only wake up
|
||||
+ * clients, which may be sleeping on individual rings
|
||||
+ * or on a global resource for all rings.
|
||||
+ */
|
||||
+ if (netmap_tx_irq(adapter->netdev, tx_ring->queue_index))
|
||||
+ return true; /* seems to be ignored */
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
tx_buffer = &tx_ring->tx_buffer_info[i];
|
||||
tx_desc = IXGBE_TX_DESC_ADV(tx_ring, i);
|
||||
|
||||
@@ -1253,6 +1280,14 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
|
||||
u16 cleaned_count = 0;
|
||||
bool pkt_is_rsc = false;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ /*
|
||||
+ * Same as the txeof routine: only wakeup clients on intr.
|
||||
+ */
|
||||
+ int dummy;
|
||||
+ if (netmap_rx_irq(adapter->netdev, rx_ring->queue_index, &dummy))
|
||||
+ return true;
|
||||
+#endif /* DEV_NETMAP */
|
||||
i = rx_ring->next_to_clean;
|
||||
rx_desc = IXGBE_RX_DESC_ADV(rx_ring, i);
|
||||
staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
|
||||
@@ -2420,6 +2455,9 @@ void ixgbe_configure_tx_ring(struct ixgbe_adapter *adapter,
|
||||
} while (--wait_loop && !(txdctl & IXGBE_TXDCTL_ENABLE));
|
||||
if (!wait_loop)
|
||||
e_err(drv, "Could not enable Tx Queue %d\n", reg_idx);
|
||||
+#ifdef DEV_NETMAP
|
||||
+ ixgbe_netmap_configure_tx_ring(adapter, reg_idx);
|
||||
+#endif /* DEV_NETMAP */
|
||||
}
|
||||
|
||||
static void ixgbe_setup_mtqc(struct ixgbe_adapter *adapter)
|
||||
@@ -2783,6 +2821,10 @@ void ixgbe_configure_rx_ring(struct ixgbe_adapter *adapter,
|
||||
IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(reg_idx), rxdctl);
|
||||
|
||||
ixgbe_rx_desc_queue_enable(adapter, ring);
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (ixgbe_netmap_configure_rx_ring(adapter, reg_idx))
|
||||
+ return;
|
||||
+#endif /* DEV_NETMAP */
|
||||
ixgbe_alloc_rx_buffers(ring, ixgbe_desc_unused(ring));
|
||||
}
|
||||
|
||||
@@ -3757,6 +3799,10 @@ static void ixgbe_up_complete(struct ixgbe_adapter *adapter)
|
||||
/* enable transmits */
|
||||
netif_tx_start_all_queues(adapter->netdev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_enable_all_rings(adapter->netdev);
|
||||
+#endif
|
||||
+
|
||||
/* bring the link up in the watchdog, this could race with our first
|
||||
* link up interrupt but shouldn't be a problem */
|
||||
adapter->flags |= IXGBE_FLAG_NEED_LINK_UPDATE;
|
||||
@@ -4007,6 +4053,10 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
|
||||
|
||||
ixgbe_napi_disable_all(adapter);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_disable_all_rings(netdev);
|
||||
+#endif
|
||||
+
|
||||
adapter->flags2 &= ~(IXGBE_FLAG2_FDIR_REQUIRES_REINIT |
|
||||
IXGBE_FLAG2_RESET_REQUESTED);
|
||||
adapter->flags &= ~IXGBE_FLAG_NEED_LINK_UPDATE;
|
||||
@@ -7710,6 +7760,11 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
|
||||
|
||||
e_dev_info("Intel(R) 10 Gigabit Network Connection\n");
|
||||
cards_found++;
|
||||
+
|
||||
+#ifdef DEV_NETMAP
|
||||
+ ixgbe_netmap_attach(adapter);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
return 0;
|
||||
|
||||
err_register:
|
124
netmap/LINUX/final-patches/diff--ixgbe--30400--30500
Normal file
124
netmap/LINUX/final-patches/diff--ixgbe--30400--30500
Normal file
@ -0,0 +1,124 @@
|
||||
diff --git a/ixgbe/ixgbe_main.c b/ixgbe/ixgbe_main.c
|
||||
index 467948e..0aa1511 100644
|
||||
--- a/ixgbe/ixgbe_main.c
|
||||
+++ b/ixgbe/ixgbe_main.c
|
||||
@@ -204,6 +204,22 @@ static const struct ixgbe_reg_info ixgbe_reg_info_tbl[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
+#if defined(CONFIG_NETMAP) || defined(CONFIG_NETMAP_MODULE)
|
||||
+/*
|
||||
+ * The #ifdef DEV_NETMAP / #endif blocks in this file are meant to
|
||||
+ * be a reference on how to implement netmap support in a driver.
|
||||
+ * Additional comments are in ixgbe_netmap_linux.h .
|
||||
+ *
|
||||
+ * The code is originally developed on FreeBSD and in the interest
|
||||
+ * of maintainability we try to limit differences between the two systems.
|
||||
+ *
|
||||
+ * <ixgbe_netmap_linux.h> contains functions for netmap support
|
||||
+ * that extend the standard driver.
|
||||
+ * It also defines DEV_NETMAP so further conditional sections use
|
||||
+ * that instead of CONFIG_NETMAP
|
||||
+ */
|
||||
+#include <ixgbe_netmap_linux.h>
|
||||
+#endif
|
||||
|
||||
/*
|
||||
* ixgbe_regdump - register printout routine
|
||||
@@ -749,6 +765,17 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
|
||||
if (test_bit(__IXGBE_DOWN, &adapter->state))
|
||||
return true;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ /*
|
||||
+ * In netmap mode, all the work is done in the context
|
||||
+ * of the client thread. Interrupt handlers only wake up
|
||||
+ * clients, which may be sleeping on individual rings
|
||||
+ * or on a global resource for all rings.
|
||||
+ */
|
||||
+ if (netmap_tx_irq(adapter->netdev, tx_ring->queue_index))
|
||||
+ return 1; /* seems to be ignored */
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
tx_buffer = &tx_ring->tx_buffer_info[i];
|
||||
tx_desc = IXGBE_TX_DESC(tx_ring, i);
|
||||
i -= tx_ring->count;
|
||||
@@ -1629,6 +1656,15 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
|
||||
#endif /* IXGBE_FCOE */
|
||||
u16 cleaned_count = ixgbe_desc_unused(rx_ring);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ /*
|
||||
+ * Same as the txeof routine: only wakeup clients on intr.
|
||||
+ */
|
||||
+ int dummy;
|
||||
+ if (netmap_rx_irq(rx_ring->netdev, rx_ring->queue_index, &dummy))
|
||||
+ return true; /* no more interrupts */
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
do {
|
||||
struct ixgbe_rx_buffer *rx_buffer;
|
||||
union ixgbe_adv_rx_desc *rx_desc;
|
||||
@@ -2683,6 +2719,9 @@ void ixgbe_configure_tx_ring(struct ixgbe_adapter *adapter,
|
||||
} while (--wait_loop && !(txdctl & IXGBE_TXDCTL_ENABLE));
|
||||
if (!wait_loop)
|
||||
e_err(drv, "Could not enable Tx Queue %d\n", reg_idx);
|
||||
+#ifdef DEV_NETMAP
|
||||
+ ixgbe_netmap_configure_tx_ring(adapter, reg_idx);
|
||||
+#endif /* DEV_NETMAP */
|
||||
}
|
||||
|
||||
static void ixgbe_setup_mtqc(struct ixgbe_adapter *adapter)
|
||||
@@ -3032,6 +3071,10 @@ void ixgbe_configure_rx_ring(struct ixgbe_adapter *adapter,
|
||||
IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(reg_idx), rxdctl);
|
||||
|
||||
ixgbe_rx_desc_queue_enable(adapter, ring);
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (ixgbe_netmap_configure_rx_ring(adapter, reg_idx))
|
||||
+ return;
|
||||
+#endif /* DEV_NETMAP */
|
||||
ixgbe_alloc_rx_buffers(ring, ixgbe_desc_unused(ring));
|
||||
}
|
||||
|
||||
@@ -3986,6 +4029,10 @@ static void ixgbe_up_complete(struct ixgbe_adapter *adapter)
|
||||
/* enable transmits */
|
||||
netif_tx_start_all_queues(adapter->netdev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_enable_all_rings(adapter->netdev);
|
||||
+#endif
|
||||
+
|
||||
/* bring the link up in the watchdog, this could race with our first
|
||||
* link up interrupt but shouldn't be a problem */
|
||||
adapter->flags |= IXGBE_FLAG_NEED_LINK_UPDATE;
|
||||
@@ -4249,6 +4296,10 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
|
||||
|
||||
ixgbe_napi_disable_all(adapter);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_disable_all_rings(netdev);
|
||||
+#endif
|
||||
+
|
||||
adapter->flags2 &= ~(IXGBE_FLAG2_FDIR_REQUIRES_REINIT |
|
||||
IXGBE_FLAG2_RESET_REQUESTED);
|
||||
adapter->flags &= ~IXGBE_FLAG_NEED_LINK_UPDATE;
|
||||
@@ -4764,6 +4815,7 @@ static int ixgbe_open(struct net_device *netdev)
|
||||
|
||||
ixgbe_up_complete(adapter);
|
||||
|
||||
+
|
||||
return 0;
|
||||
|
||||
err_req_irq:
|
||||
@@ -7152,6 +7204,11 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
|
||||
|
||||
e_dev_info("%s\n", ixgbe_default_device_descr);
|
||||
cards_found++;
|
||||
+
|
||||
+#ifdef DEV_NETMAP
|
||||
+ ixgbe_netmap_attach(adapter);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
return 0;
|
||||
|
||||
err_register:
|
123
netmap/LINUX/final-patches/diff--ixgbe--30500--30900
Normal file
123
netmap/LINUX/final-patches/diff--ixgbe--30500--30900
Normal file
@ -0,0 +1,123 @@
|
||||
diff --git a/ixgbe/ixgbe_main.c b/ixgbe/ixgbe_main.c
|
||||
index e242104..02e1544 100644
|
||||
--- a/ixgbe/ixgbe_main.c
|
||||
+++ b/ixgbe/ixgbe_main.c
|
||||
@@ -204,6 +204,22 @@ static const struct ixgbe_reg_info ixgbe_reg_info_tbl[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
+#if defined(CONFIG_NETMAP) || defined(CONFIG_NETMAP_MODULE)
|
||||
+/*
|
||||
+ * The #ifdef DEV_NETMAP / #endif blocks in this file are meant to
|
||||
+ * be a reference on how to implement netmap support in a driver.
|
||||
+ * Additional comments are in ixgbe_netmap_linux.h .
|
||||
+ *
|
||||
+ * The code is originally developed on FreeBSD and in the interest
|
||||
+ * of maintainability we try to limit differences between the two systems.
|
||||
+ *
|
||||
+ * <ixgbe_netmap_linux.h> contains functions for netmap support
|
||||
+ * that extend the standard driver.
|
||||
+ * It also defines DEV_NETMAP so further conditional sections use
|
||||
+ * that instead of CONFIG_NETMAP
|
||||
+ */
|
||||
+#include <ixgbe_netmap_linux.h>
|
||||
+#endif
|
||||
|
||||
/*
|
||||
* ixgbe_regdump - register printout routine
|
||||
@@ -764,6 +780,17 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
|
||||
if (test_bit(__IXGBE_DOWN, &adapter->state))
|
||||
return true;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ /*
|
||||
+ * In netmap mode, all the work is done in the context
|
||||
+ * of the client thread. Interrupt handlers only wake up
|
||||
+ * clients, which may be sleeping on individual rings
|
||||
+ * or on a global resource for all rings.
|
||||
+ */
|
||||
+ if (netmap_tx_irq(adapter->netdev, tx_ring->queue_index))
|
||||
+ return 1; /* seems to be ignored */
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
tx_buffer = &tx_ring->tx_buffer_info[i];
|
||||
tx_desc = IXGBE_TX_DESC(tx_ring, i);
|
||||
i -= tx_ring->count;
|
||||
@@ -1665,6 +1692,15 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
|
||||
#endif /* IXGBE_FCOE */
|
||||
u16 cleaned_count = ixgbe_desc_unused(rx_ring);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ /*
|
||||
+ * Same as the txeof routine: only wakeup clients on intr.
|
||||
+ */
|
||||
+ int dummy;
|
||||
+ if (netmap_rx_irq(rx_ring->netdev, rx_ring->queue_index, &dummy))
|
||||
+ return true; /* no more interrupts */
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
do {
|
||||
struct ixgbe_rx_buffer *rx_buffer;
|
||||
union ixgbe_adv_rx_desc *rx_desc;
|
||||
@@ -2725,6 +2761,9 @@ void ixgbe_configure_tx_ring(struct ixgbe_adapter *adapter,
|
||||
} while (--wait_loop && !(txdctl & IXGBE_TXDCTL_ENABLE));
|
||||
if (!wait_loop)
|
||||
e_err(drv, "Could not enable Tx Queue %d\n", reg_idx);
|
||||
+#ifdef DEV_NETMAP
|
||||
+ ixgbe_netmap_configure_tx_ring(adapter, reg_idx);
|
||||
+#endif /* DEV_NETMAP */
|
||||
}
|
||||
|
||||
static void ixgbe_setup_mtqc(struct ixgbe_adapter *adapter)
|
||||
@@ -3102,6 +3141,10 @@ void ixgbe_configure_rx_ring(struct ixgbe_adapter *adapter,
|
||||
IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(reg_idx), rxdctl);
|
||||
|
||||
ixgbe_rx_desc_queue_enable(adapter, ring);
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (ixgbe_netmap_configure_rx_ring(adapter, reg_idx))
|
||||
+ return;
|
||||
+#endif /* DEV_NETMAP */
|
||||
ixgbe_alloc_rx_buffers(ring, ixgbe_desc_unused(ring));
|
||||
}
|
||||
|
||||
@@ -4051,6 +4094,10 @@ static void ixgbe_up_complete(struct ixgbe_adapter *adapter)
|
||||
/* enable transmits */
|
||||
netif_tx_start_all_queues(adapter->netdev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_enable_all_rings(adapter->netdev);
|
||||
+#endif
|
||||
+
|
||||
/* bring the link up in the watchdog, this could race with our first
|
||||
* link up interrupt but shouldn't be a problem */
|
||||
adapter->flags |= IXGBE_FLAG_NEED_LINK_UPDATE;
|
||||
@@ -4315,6 +4362,10 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
|
||||
|
||||
ixgbe_napi_disable_all(adapter);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_disable_all_rings(netdev);
|
||||
+#endif
|
||||
+
|
||||
adapter->flags2 &= ~(IXGBE_FLAG2_FDIR_REQUIRES_REINIT |
|
||||
IXGBE_FLAG2_RESET_REQUESTED);
|
||||
adapter->flags &= ~IXGBE_FLAG_NEED_LINK_UPDATE;
|
||||
@@ -4827,6 +4878,7 @@ static int ixgbe_open(struct net_device *netdev)
|
||||
|
||||
ixgbe_up_complete(adapter);
|
||||
|
||||
+
|
||||
return 0;
|
||||
|
||||
err_req_irq:
|
||||
@@ -7358,6 +7410,10 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
|
||||
e_err(probe, "failed to allocate sysfs resources\n");
|
||||
#endif /* CONFIG_IXGBE_HWMON */
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ ixgbe_netmap_attach(adapter);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
return 0;
|
||||
|
||||
err_register:
|
134
netmap/LINUX/final-patches/diff--ixgbe--30900--30a00
Normal file
134
netmap/LINUX/final-patches/diff--ixgbe--30900--30a00
Normal file
@ -0,0 +1,134 @@
|
||||
diff --git a/ixgbe/ixgbe_main.c b/ixgbe/ixgbe_main.c
|
||||
index 79f4a26..4b8a25b 100644
|
||||
--- a/ixgbe/ixgbe_main.c
|
||||
+++ b/ixgbe/ixgbe_main.c
|
||||
@@ -202,6 +202,22 @@ static const struct ixgbe_reg_info ixgbe_reg_info_tbl[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
+#if defined(CONFIG_NETMAP) || defined(CONFIG_NETMAP_MODULE)
|
||||
+/*
|
||||
+ * The #ifdef DEV_NETMAP / #endif blocks in this file are meant to
|
||||
+ * be a reference on how to implement netmap support in a driver.
|
||||
+ * Additional comments are in ixgbe_netmap_linux.h .
|
||||
+ *
|
||||
+ * The code is originally developed on FreeBSD and in the interest
|
||||
+ * of maintainability we try to limit differences between the two systems.
|
||||
+ *
|
||||
+ * <ixgbe_netmap_linux.h> contains functions for netmap support
|
||||
+ * that extend the standard driver.
|
||||
+ * It also defines DEV_NETMAP so further conditional sections use
|
||||
+ * that instead of CONFIG_NETMAP
|
||||
+ */
|
||||
+#include <ixgbe_netmap_linux.h>
|
||||
+#endif
|
||||
|
||||
/*
|
||||
* ixgbe_regdump - register printout routine
|
||||
@@ -826,6 +842,17 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
|
||||
if (test_bit(__IXGBE_DOWN, &adapter->state))
|
||||
return true;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ /*
|
||||
+ * In netmap mode, all the work is done in the context
|
||||
+ * of the client thread. Interrupt handlers only wake up
|
||||
+ * clients, which may be sleeping on individual rings
|
||||
+ * or on a global resource for all rings.
|
||||
+ */
|
||||
+ if (netmap_tx_irq(adapter->netdev, tx_ring->queue_index))
|
||||
+ return 1; /* seems to be ignored */
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
tx_buffer = &tx_ring->tx_buffer_info[i];
|
||||
tx_desc = IXGBE_TX_DESC(tx_ring, i);
|
||||
i -= tx_ring->count;
|
||||
@@ -1860,6 +1887,15 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
|
||||
#endif /* IXGBE_FCOE */
|
||||
u16 cleaned_count = ixgbe_desc_unused(rx_ring);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ /*
|
||||
+ * Same as the txeof routine: only wakeup clients on intr.
|
||||
+ */
|
||||
+ int dummy;
|
||||
+ if (netmap_rx_irq(rx_ring->netdev, rx_ring->queue_index, &dummy))
|
||||
+ return true; /* no more interrupts */
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
do {
|
||||
union ixgbe_adv_rx_desc *rx_desc;
|
||||
struct sk_buff *skb;
|
||||
@@ -2846,6 +2882,9 @@ void ixgbe_configure_tx_ring(struct ixgbe_adapter *adapter,
|
||||
} while (--wait_loop && !(txdctl & IXGBE_TXDCTL_ENABLE));
|
||||
if (!wait_loop)
|
||||
e_err(drv, "Could not enable Tx Queue %d\n", reg_idx);
|
||||
+#ifdef DEV_NETMAP
|
||||
+ ixgbe_netmap_configure_tx_ring(adapter, reg_idx);
|
||||
+#endif /* DEV_NETMAP */
|
||||
}
|
||||
|
||||
static void ixgbe_setup_mtqc(struct ixgbe_adapter *adapter)
|
||||
@@ -3207,6 +3246,10 @@ void ixgbe_configure_rx_ring(struct ixgbe_adapter *adapter,
|
||||
IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(reg_idx), rxdctl);
|
||||
|
||||
ixgbe_rx_desc_queue_enable(adapter, ring);
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (ixgbe_netmap_configure_rx_ring(adapter, reg_idx))
|
||||
+ return;
|
||||
+#endif /* DEV_NETMAP */
|
||||
ixgbe_alloc_rx_buffers(ring, ixgbe_desc_unused(ring));
|
||||
}
|
||||
|
||||
@@ -4155,6 +4198,10 @@ static void ixgbe_up_complete(struct ixgbe_adapter *adapter)
|
||||
/* enable transmits */
|
||||
netif_tx_start_all_queues(adapter->netdev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_enable_all_rings(adapter->netdev);
|
||||
+#endif
|
||||
+
|
||||
/* bring the link up in the watchdog, this could race with our first
|
||||
* link up interrupt but shouldn't be a problem */
|
||||
adapter->flags |= IXGBE_FLAG_NEED_LINK_UPDATE;
|
||||
@@ -4402,6 +4449,10 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
|
||||
|
||||
ixgbe_napi_disable_all(adapter);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_disable_all_rings(netdev);
|
||||
+#endif
|
||||
+
|
||||
adapter->flags2 &= ~(IXGBE_FLAG2_FDIR_REQUIRES_REINIT |
|
||||
IXGBE_FLAG2_RESET_REQUESTED);
|
||||
adapter->flags &= ~IXGBE_FLAG_NEED_LINK_UPDATE;
|
||||
@@ -4976,6 +5027,7 @@ static int ixgbe_open(struct net_device *netdev)
|
||||
|
||||
ixgbe_up_complete(adapter);
|
||||
|
||||
+
|
||||
return 0;
|
||||
|
||||
err_set_queues:
|
||||
@@ -7619,6 +7671,10 @@ skip_sriov:
|
||||
ixgbe_dbg_adapter_init(adapter);
|
||||
#endif /* CONFIG_DEBUG_FS */
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ ixgbe_netmap_attach(adapter);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
return 0;
|
||||
|
||||
err_register:
|
||||
@@ -7653,6 +7709,10 @@ static void ixgbe_remove(struct pci_dev *pdev)
|
||||
struct ixgbe_adapter *adapter = pci_get_drvdata(pdev);
|
||||
struct net_device *netdev = adapter->netdev;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_detach(netdev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
ixgbe_dbg_adapter_exit(adapter);
|
||||
#endif /*CONFIG_DEBUG_FS */
|
123
netmap/LINUX/final-patches/diff--ixgbe--30a00--99999
Normal file
123
netmap/LINUX/final-patches/diff--ixgbe--30a00--99999
Normal file
@ -0,0 +1,123 @@
|
||||
diff --git a/ixgbe/ixgbe_main.c b/ixgbe/ixgbe_main.c
|
||||
index d30fbdd..7418c57 100644
|
||||
--- a/ixgbe/ixgbe_main.c
|
||||
+++ b/ixgbe/ixgbe_main.c
|
||||
@@ -248,6 +248,22 @@ static const struct ixgbe_reg_info ixgbe_reg_info_tbl[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
+#if defined(CONFIG_NETMAP) || defined(CONFIG_NETMAP_MODULE)
|
||||
+/*
|
||||
+ * The #ifdef DEV_NETMAP / #endif blocks in this file are meant to
|
||||
+ * be a reference on how to implement netmap support in a driver.
|
||||
+ * Additional comments are in ixgbe_netmap_linux.h .
|
||||
+ *
|
||||
+ * The code is originally developed on FreeBSD and in the interest
|
||||
+ * of maintainability we try to limit differences between the two systems.
|
||||
+ *
|
||||
+ * <ixgbe_netmap_linux.h> contains functions for netmap support
|
||||
+ * that extend the standard driver.
|
||||
+ * It also defines DEV_NETMAP so further conditional sections use
|
||||
+ * that instead of CONFIG_NETMAP
|
||||
+ */
|
||||
+#include <ixgbe_netmap_linux.h>
|
||||
+#endif
|
||||
|
||||
/*
|
||||
* ixgbe_regdump - register printout routine
|
||||
@@ -872,6 +888,17 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
|
||||
if (test_bit(__IXGBE_DOWN, &adapter->state))
|
||||
return true;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ /*
|
||||
+ * In netmap mode, all the work is done in the context
|
||||
+ * of the client thread. Interrupt handlers only wake up
|
||||
+ * clients, which may be sleeping on individual rings
|
||||
+ * or on a global resource for all rings.
|
||||
+ */
|
||||
+ if (netmap_tx_irq(adapter->netdev, tx_ring->queue_index))
|
||||
+ return 1; /* seems to be ignored */
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
tx_buffer = &tx_ring->tx_buffer_info[i];
|
||||
tx_desc = IXGBE_TX_DESC(tx_ring, i);
|
||||
i -= tx_ring->count;
|
||||
@@ -1906,6 +1933,15 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
|
||||
#endif /* IXGBE_FCOE */
|
||||
u16 cleaned_count = ixgbe_desc_unused(rx_ring);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ /*
|
||||
+ * Same as the txeof routine: only wakeup clients on intr.
|
||||
+ */
|
||||
+ int dummy;
|
||||
+ if (netmap_rx_irq(rx_ring->netdev, rx_ring->queue_index, &dummy))
|
||||
+ return true; /* no more interrupts */
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
do {
|
||||
union ixgbe_adv_rx_desc *rx_desc;
|
||||
struct sk_buff *skb;
|
||||
@@ -2905,6 +2941,9 @@ void ixgbe_configure_tx_ring(struct ixgbe_adapter *adapter,
|
||||
} while (--wait_loop && !(txdctl & IXGBE_TXDCTL_ENABLE));
|
||||
if (!wait_loop)
|
||||
e_err(drv, "Could not enable Tx Queue %d\n", reg_idx);
|
||||
+#ifdef DEV_NETMAP
|
||||
+ ixgbe_netmap_configure_tx_ring(adapter, reg_idx);
|
||||
+#endif /* DEV_NETMAP */
|
||||
}
|
||||
|
||||
static void ixgbe_setup_mtqc(struct ixgbe_adapter *adapter)
|
||||
@@ -3266,6 +3305,10 @@ void ixgbe_configure_rx_ring(struct ixgbe_adapter *adapter,
|
||||
IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(reg_idx), rxdctl);
|
||||
|
||||
ixgbe_rx_desc_queue_enable(adapter, ring);
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (ixgbe_netmap_configure_rx_ring(adapter, reg_idx))
|
||||
+ return;
|
||||
+#endif /* DEV_NETMAP */
|
||||
ixgbe_alloc_rx_buffers(ring, ixgbe_desc_unused(ring));
|
||||
}
|
||||
|
||||
@@ -4216,6 +4259,10 @@ static void ixgbe_up_complete(struct ixgbe_adapter *adapter)
|
||||
/* enable transmits */
|
||||
netif_tx_start_all_queues(adapter->netdev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_enable_all_rings(adapter->netdev);
|
||||
+#endif
|
||||
+
|
||||
/* bring the link up in the watchdog, this could race with our first
|
||||
* link up interrupt but shouldn't be a problem */
|
||||
adapter->flags |= IXGBE_FLAG_NEED_LINK_UPDATE;
|
||||
@@ -4463,6 +4510,10 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
|
||||
|
||||
ixgbe_napi_disable_all(adapter);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_disable_all_rings(netdev);
|
||||
+#endif
|
||||
+
|
||||
adapter->flags2 &= ~(IXGBE_FLAG2_FDIR_REQUIRES_REINIT |
|
||||
IXGBE_FLAG2_RESET_REQUESTED);
|
||||
adapter->flags &= ~IXGBE_FLAG_NEED_LINK_UPDATE;
|
||||
@@ -5037,6 +5088,7 @@ static int ixgbe_open(struct net_device *netdev)
|
||||
|
||||
ixgbe_up_complete(adapter);
|
||||
|
||||
+
|
||||
return 0;
|
||||
|
||||
err_set_queues:
|
||||
@@ -7658,6 +7710,10 @@ skip_sriov:
|
||||
IXGBE_LINK_SPEED_10GB_FULL | IXGBE_LINK_SPEED_1GB_FULL,
|
||||
true);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ ixgbe_netmap_attach(adapter);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
return 0;
|
||||
|
||||
err_register:
|
117
netmap/LINUX/final-patches/diff--r8169.c--20620--20625
Normal file
117
netmap/LINUX/final-patches/diff--r8169.c--20620--20625
Normal file
@ -0,0 +1,117 @@
|
||||
diff --git a/r8169.c b/r8169.c
|
||||
index 0fe2fc9..efee0a4 100644
|
||||
--- a/r8169.c
|
||||
+++ b/r8169.c
|
||||
@@ -537,6 +537,10 @@ static int rtl8169_poll(struct napi_struct *napi, int budget);
|
||||
static const unsigned int rtl8169_rx_config =
|
||||
(RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift);
|
||||
|
||||
+#if defined(CONFIG_NETMAP) || defined(CONFIG_NETMAP_MODULE)
|
||||
+#include <if_re_netmap_linux.h>
|
||||
+#endif
|
||||
+
|
||||
static void mdio_write(void __iomem *ioaddr, int reg_addr, int value)
|
||||
{
|
||||
int i;
|
||||
@@ -3210,6 +3214,10 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
|
||||
device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ re_netmap_attach(tp);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
out:
|
||||
return rc;
|
||||
|
||||
@@ -3236,6 +3244,10 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev)
|
||||
|
||||
unregister_netdev(dev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_detach(dev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
/* restore original MAC address */
|
||||
rtl_rar_set(tp, dev->perm_addr);
|
||||
|
||||
@@ -3291,6 +3303,10 @@ static int rtl8169_open(struct net_device *dev)
|
||||
|
||||
napi_enable(&tp->napi);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_enable_all_rings(dev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
rtl_hw_start(dev);
|
||||
|
||||
rtl8169_request_timer(dev);
|
||||
@@ -3993,6 +4009,11 @@ err_out:
|
||||
static void rtl8169_rx_clear(struct rtl8169_private *tp)
|
||||
{
|
||||
unsigned int i;
|
||||
+#ifdef DEV_NETMAP
|
||||
+ re_netmap_tx_init(tp);
|
||||
+ if (re_netmap_rx_init(tp))
|
||||
+ return 0; // success
|
||||
+#endif /* DEV_NETMAP */
|
||||
|
||||
for (i = 0; i < NUM_RX_DESC; i++) {
|
||||
if (tp->Rx_skbuff[i]) {
|
||||
@@ -4112,11 +4133,19 @@ static void rtl8169_wait_for_quiescence(struct net_device *dev)
|
||||
/* Wait for any pending NAPI task to complete */
|
||||
napi_disable(&tp->napi);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_disable_all_rings(dev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
rtl8169_irq_mask_and_ack(ioaddr);
|
||||
|
||||
tp->intr_mask = 0xffff;
|
||||
RTL_W16(IntrMask, tp->intr_event);
|
||||
napi_enable(&tp->napi);
|
||||
+
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_enable_all_rings(dev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
}
|
||||
|
||||
static void rtl8169_reinit_task(struct work_struct *work)
|
||||
@@ -4372,6 +4401,11 @@ static void rtl8169_tx_interrupt(struct net_device *dev,
|
||||
{
|
||||
unsigned int dirty_tx, tx_left;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (netmap_tx_irq(dev, 0))
|
||||
+ return;
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
dirty_tx = tp->dirty_tx;
|
||||
smp_rmb();
|
||||
tx_left = tp->cur_tx - dirty_tx;
|
||||
@@ -4468,6 +4502,11 @@ static int rtl8169_rx_interrupt(struct net_device *dev,
|
||||
unsigned int cur_rx, rx_left;
|
||||
unsigned int delta, count;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (netmap_rx_irq(dev, 0, &count))
|
||||
+ return count;
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
cur_rx = tp->cur_rx;
|
||||
rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx;
|
||||
rx_left = min(rx_left, budget);
|
||||
@@ -4687,7 +4726,12 @@ static void rtl8169_down(struct net_device *dev)
|
||||
|
||||
napi_disable(&tp->napi);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_disable_all_rings(dev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
core_down:
|
||||
+
|
||||
spin_lock_irq(&tp->lock);
|
||||
|
||||
rtl8169_asic_down(ioaddr);
|
115
netmap/LINUX/final-patches/diff--r8169.c--20625--20626
Normal file
115
netmap/LINUX/final-patches/diff--r8169.c--20625--20626
Normal file
@ -0,0 +1,115 @@
|
||||
diff --git a/r8169.c b/r8169.c
|
||||
index 53b13de..745a59d 100644
|
||||
--- a/r8169.c
|
||||
+++ b/r8169.c
|
||||
@@ -535,6 +535,10 @@ static int rtl8169_poll(struct napi_struct *napi, int budget);
|
||||
static const unsigned int rtl8169_rx_config =
|
||||
(RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift);
|
||||
|
||||
+#if defined(CONFIG_NETMAP) || defined(CONFIG_NETMAP_MODULE)
|
||||
+#include <if_re_netmap_linux.h>
|
||||
+#endif
|
||||
+
|
||||
static void mdio_write(void __iomem *ioaddr, int reg_addr, int value)
|
||||
{
|
||||
int i;
|
||||
@@ -3229,6 +3233,10 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
if (pci_dev_run_wake(pdev))
|
||||
pm_runtime_put_noidle(&pdev->dev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ re_netmap_attach(tp);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
out:
|
||||
return rc;
|
||||
|
||||
@@ -3257,6 +3265,10 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev)
|
||||
if (pci_dev_run_wake(pdev))
|
||||
pm_runtime_get_noresume(&pdev->dev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_detach(dev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
/* restore original MAC address */
|
||||
rtl_rar_set(tp, dev->perm_addr);
|
||||
|
||||
@@ -3303,6 +3315,10 @@ static int rtl8169_open(struct net_device *dev)
|
||||
|
||||
napi_enable(&tp->napi);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_enable_all_rings(dev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
rtl_hw_start(dev);
|
||||
|
||||
rtl8169_request_timer(dev);
|
||||
@@ -4018,6 +4034,11 @@ static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc)
|
||||
static int rtl8169_rx_fill(struct rtl8169_private *tp)
|
||||
{
|
||||
unsigned int i;
|
||||
+#ifdef DEV_NETMAP
|
||||
+ re_netmap_tx_init(tp);
|
||||
+ if (re_netmap_rx_init(tp))
|
||||
+ return 0; // success
|
||||
+#endif /* DEV_NETMAP */
|
||||
|
||||
for (i = 0; i < NUM_RX_DESC; i++) {
|
||||
void *data;
|
||||
@@ -4119,11 +4140,19 @@ static void rtl8169_wait_for_quiescence(struct net_device *dev)
|
||||
/* Wait for any pending NAPI task to complete */
|
||||
napi_disable(&tp->napi);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_disable_all_rings(dev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
rtl8169_irq_mask_and_ack(ioaddr);
|
||||
|
||||
tp->intr_mask = 0xffff;
|
||||
RTL_W16(IntrMask, tp->intr_event);
|
||||
napi_enable(&tp->napi);
|
||||
+
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_enable_all_rings(dev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
}
|
||||
|
||||
static void rtl8169_reinit_task(struct work_struct *work)
|
||||
@@ -4395,6 +4424,11 @@ static void rtl8169_tx_interrupt(struct net_device *dev,
|
||||
{
|
||||
unsigned int dirty_tx, tx_left;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (netmap_tx_irq(dev, 0))
|
||||
+ return;
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
dirty_tx = tp->dirty_tx;
|
||||
smp_rmb();
|
||||
tx_left = tp->cur_tx - dirty_tx;
|
||||
@@ -4490,6 +4524,11 @@ static int rtl8169_rx_interrupt(struct net_device *dev,
|
||||
unsigned int count;
|
||||
int polling = (budget != ~(u32)0) ? 1 : 0;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (netmap_rx_irq(dev, 0, &count))
|
||||
+ return count;
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
cur_rx = tp->cur_rx;
|
||||
rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx;
|
||||
rx_left = min(rx_left, budget);
|
||||
@@ -4691,6 +4730,10 @@ static void rtl8169_down(struct net_device *dev)
|
||||
|
||||
napi_disable(&tp->napi);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_disable_all_rings(dev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
spin_lock_irq(&tp->lock);
|
||||
|
||||
rtl8169_asic_down(ioaddr);
|
114
netmap/LINUX/final-patches/diff--r8169.c--20626--30200
Normal file
114
netmap/LINUX/final-patches/diff--r8169.c--20626--30200
Normal file
@ -0,0 +1,114 @@
|
||||
diff --git a/r8169.c b/r8169.c
|
||||
index 7ffdb80..6bae7e6 100644
|
||||
--- a/r8169.c
|
||||
+++ b/r8169.c
|
||||
@@ -590,6 +590,10 @@ static int rtl8169_poll(struct napi_struct *napi, int budget);
|
||||
static const unsigned int rtl8169_rx_config =
|
||||
(RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift);
|
||||
|
||||
+#if defined(CONFIG_NETMAP) || defined(CONFIG_NETMAP_MODULE)
|
||||
+#include <if_re_netmap_linux.h>
|
||||
+#endif
|
||||
+
|
||||
static u32 ocp_read(struct rtl8169_private *tp, u8 mask, u16 reg)
|
||||
{
|
||||
void __iomem *ioaddr = tp->mmio_addr;
|
||||
@@ -3207,6 +3211,10 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
if (pci_dev_run_wake(pdev))
|
||||
pm_runtime_put_noidle(&pdev->dev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ re_netmap_attach(tp);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
netif_carrier_off(dev);
|
||||
|
||||
out:
|
||||
@@ -3238,6 +3246,9 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev)
|
||||
cancel_delayed_work_sync(&tp->task);
|
||||
|
||||
rtl_release_firmware(tp);
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_detach(dev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
|
||||
unregister_netdev(dev);
|
||||
|
||||
@@ -3291,6 +3302,10 @@ static int rtl8169_open(struct net_device *dev)
|
||||
|
||||
napi_enable(&tp->napi);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_enable_all_rings(dev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
rtl8169_init_phy(dev, tp);
|
||||
|
||||
/*
|
||||
@@ -4074,6 +4089,11 @@ static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc)
|
||||
static int rtl8169_rx_fill(struct rtl8169_private *tp)
|
||||
{
|
||||
unsigned int i;
|
||||
+#ifdef DEV_NETMAP
|
||||
+ re_netmap_tx_init(tp);
|
||||
+ if (re_netmap_rx_init(tp))
|
||||
+ return 0; // success
|
||||
+#endif /* DEV_NETMAP */
|
||||
|
||||
for (i = 0; i < NUM_RX_DESC; i++) {
|
||||
void *data;
|
||||
@@ -4175,11 +4195,19 @@ static void rtl8169_wait_for_quiescence(struct net_device *dev)
|
||||
/* Wait for any pending NAPI task to complete */
|
||||
napi_disable(&tp->napi);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_disable_all_rings(dev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
rtl8169_irq_mask_and_ack(ioaddr);
|
||||
|
||||
tp->intr_mask = 0xffff;
|
||||
RTL_W16(IntrMask, tp->intr_event);
|
||||
napi_enable(&tp->napi);
|
||||
+
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_enable_all_rings(dev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
}
|
||||
|
||||
static void rtl8169_reinit_task(struct work_struct *work)
|
||||
@@ -4452,6 +4480,11 @@ static void rtl8169_tx_interrupt(struct net_device *dev,
|
||||
{
|
||||
unsigned int dirty_tx, tx_left;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (netmap_tx_irq(dev, 0))
|
||||
+ return;
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
dirty_tx = tp->dirty_tx;
|
||||
smp_rmb();
|
||||
tx_left = tp->cur_tx - dirty_tx;
|
||||
@@ -4547,6 +4580,11 @@ static int rtl8169_rx_interrupt(struct net_device *dev,
|
||||
unsigned int count;
|
||||
int polling = (budget != ~(u32)0) ? 1 : 0;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (netmap_rx_irq(dev, 0, &count))
|
||||
+ return count;
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
cur_rx = tp->cur_rx;
|
||||
rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx;
|
||||
rx_left = min(rx_left, budget);
|
||||
@@ -4769,6 +4807,10 @@ static void rtl8169_down(struct net_device *dev)
|
||||
|
||||
napi_disable(&tp->napi);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_disable_all_rings(dev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
spin_lock_irq(&tp->lock);
|
||||
|
||||
rtl8169_asic_down(ioaddr);
|
114
netmap/LINUX/final-patches/diff--r8169.c--30200--30400
Normal file
114
netmap/LINUX/final-patches/diff--r8169.c--30200--30400
Normal file
@ -0,0 +1,114 @@
|
||||
diff --git a/r8169.c b/r8169.c
|
||||
index c8f47f1..a41e878 100644
|
||||
--- a/r8169.c
|
||||
+++ b/r8169.c
|
||||
@@ -787,6 +787,10 @@ static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force)
|
||||
}
|
||||
}
|
||||
|
||||
+#if defined(CONFIG_NETMAP) || defined(CONFIG_NETMAP_MODULE)
|
||||
+#include <if_re_netmap_linux.h>
|
||||
+#endif
|
||||
+
|
||||
static u32 ocp_read(struct rtl8169_private *tp, u8 mask, u16 reg)
|
||||
{
|
||||
void __iomem *ioaddr = tp->mmio_addr;
|
||||
@@ -4167,6 +4171,10 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
if (pci_dev_run_wake(pdev))
|
||||
pm_runtime_put_noidle(&pdev->dev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ re_netmap_attach(tp);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
netif_carrier_off(dev);
|
||||
|
||||
out:
|
||||
@@ -4201,6 +4209,9 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev)
|
||||
unregister_netdev(dev);
|
||||
|
||||
rtl_release_firmware(tp);
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_detach(dev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
|
||||
if (pci_dev_run_wake(pdev))
|
||||
pm_runtime_get_noresume(&pdev->dev);
|
||||
@@ -4298,6 +4309,10 @@ static int rtl8169_open(struct net_device *dev)
|
||||
|
||||
napi_enable(&tp->napi);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_enable_all_rings(dev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
rtl8169_init_phy(dev, tp);
|
||||
|
||||
rtl8169_set_features(dev, dev->features);
|
||||
@@ -5252,6 +5267,11 @@ static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc)
|
||||
static int rtl8169_rx_fill(struct rtl8169_private *tp)
|
||||
{
|
||||
unsigned int i;
|
||||
+#ifdef DEV_NETMAP
|
||||
+ re_netmap_tx_init(tp);
|
||||
+ if (re_netmap_rx_init(tp))
|
||||
+ return 0; // success
|
||||
+#endif /* DEV_NETMAP */
|
||||
|
||||
for (i = 0; i < NUM_RX_DESC; i++) {
|
||||
void *data;
|
||||
@@ -5348,11 +5368,19 @@ static void rtl8169_wait_for_quiescence(struct net_device *dev)
|
||||
/* Wait for any pending NAPI task to complete */
|
||||
napi_disable(&tp->napi);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_disable_all_rings(dev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
rtl8169_irq_mask_and_ack(tp);
|
||||
|
||||
tp->intr_mask = 0xffff;
|
||||
RTL_W16(IntrMask, tp->intr_event);
|
||||
napi_enable(&tp->napi);
|
||||
+
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_enable_all_rings(dev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
}
|
||||
|
||||
static void rtl8169_reinit_task(struct work_struct *work)
|
||||
@@ -5627,6 +5655,11 @@ static void rtl8169_tx_interrupt(struct net_device *dev,
|
||||
{
|
||||
unsigned int dirty_tx, tx_left;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (netmap_tx_irq(dev, 0))
|
||||
+ return;
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
dirty_tx = tp->dirty_tx;
|
||||
smp_rmb();
|
||||
tx_left = tp->cur_tx - dirty_tx;
|
||||
@@ -5714,6 +5747,11 @@ static int rtl8169_rx_interrupt(struct net_device *dev,
|
||||
unsigned int cur_rx, rx_left;
|
||||
unsigned int count;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (netmap_rx_irq(dev, 0, &count))
|
||||
+ return count;
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
cur_rx = tp->cur_rx;
|
||||
rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx;
|
||||
rx_left = min(rx_left, budget);
|
||||
@@ -5920,6 +5958,10 @@ static void rtl8169_down(struct net_device *dev)
|
||||
|
||||
napi_disable(&tp->napi);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_disable_all_rings(dev);
|
||||
+#endif /* DEV_NETMAP */
|
||||
+
|
||||
spin_lock_irq(&tp->lock);
|
||||
|
||||
rtl8169_hw_reset(tp);
|
85
netmap/LINUX/final-patches/diff--virtio_net.c--20622--20625
Normal file
85
netmap/LINUX/final-patches/diff--virtio_net.c--20622--20625
Normal file
@ -0,0 +1,85 @@
|
||||
diff --git a/virtio_net.c b/virtio_net.c
|
||||
index b0577dd..6516934 100644
|
||||
--- a/virtio_net.c
|
||||
+++ b/virtio_net.c
|
||||
@@ -64,6 +64,10 @@ struct virtnet_info
|
||||
struct page *pages;
|
||||
};
|
||||
|
||||
+#if defined(CONFIG_NETMAP) || defined(CONFIG_NETMAP_MODULE)
|
||||
+#include <virtio_netmap.h>
|
||||
+#endif
|
||||
+
|
||||
struct skb_vnet_hdr {
|
||||
union {
|
||||
struct virtio_net_hdr hdr;
|
||||
@@ -121,6 +125,10 @@ static void skb_xmit_done(struct virtqueue *svq)
|
||||
/* Suppress further interrupts. */
|
||||
svq->vq_ops->disable_cb(svq);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (netmap_tx_irq(vi->dev, 0))
|
||||
+ return;
|
||||
+#endif
|
||||
/* We were probably waiting for more output buffers. */
|
||||
netif_wake_queue(vi->dev);
|
||||
}
|
||||
@@ -470,7 +478,16 @@ static int virtnet_poll(struct napi_struct *napi, int budget)
|
||||
struct virtnet_info *vi = container_of(napi, struct virtnet_info, napi);
|
||||
void *buf;
|
||||
unsigned int len, received = 0;
|
||||
+#ifdef DEV_NETMAP
|
||||
+ int work_done = 0;
|
||||
|
||||
+ if (netmap_rx_irq(vi->dev, 0, &work_done)) {
|
||||
+ napi_complete(napi);
|
||||
+ ND("called netmap_rx_irq");
|
||||
+
|
||||
+ return 1;
|
||||
+ }
|
||||
+#endif
|
||||
again:
|
||||
while (received < budget &&
|
||||
(buf = vi->rvq->vq_ops->get_buf(vi->rvq, &len)) != NULL) {
|
||||
@@ -638,6 +655,10 @@ static int virtnet_open(struct net_device *dev)
|
||||
{
|
||||
struct virtnet_info *vi = netdev_priv(dev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ virtio_netmap_init_buffers(vi);
|
||||
+ netmap_enable_all_rings(dev);
|
||||
+#endif
|
||||
napi_enable(&vi->napi);
|
||||
|
||||
/* If all buffers were filled by other side before we napi_enabled, we
|
||||
@@ -700,6 +721,9 @@ static int virtnet_close(struct net_device *dev)
|
||||
{
|
||||
struct virtnet_info *vi = netdev_priv(dev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_disable_all_rings(dev);
|
||||
+#endif
|
||||
napi_disable(&vi->napi);
|
||||
|
||||
return 0;
|
||||
@@ -985,6 +1009,10 @@ static int virtnet_probe(struct virtio_device *vdev)
|
||||
goto unregister;
|
||||
}
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ virtio_netmap_attach(vi);
|
||||
+#endif
|
||||
+
|
||||
vi->status = VIRTIO_NET_S_LINK_UP;
|
||||
virtnet_update_status(vi);
|
||||
netif_carrier_on(dev);
|
||||
@@ -1028,6 +1056,9 @@ static void __devexit virtnet_remove(struct virtio_device *vdev)
|
||||
{
|
||||
struct virtnet_info *vi = vdev->priv;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_detach(vi->dev);
|
||||
+#endif
|
||||
/* Stop all the virtqueues. */
|
||||
vdev->config->reset(vdev);
|
||||
|
85
netmap/LINUX/final-patches/diff--virtio_net.c--20625--20626
Normal file
85
netmap/LINUX/final-patches/diff--virtio_net.c--20625--20626
Normal file
@ -0,0 +1,85 @@
|
||||
diff --git a/virtio_net.c b/virtio_net.c
|
||||
index b6d4028..a9be38d 100644
|
||||
--- a/virtio_net.c
|
||||
+++ b/virtio_net.c
|
||||
@@ -67,6 +67,10 @@ struct virtnet_info {
|
||||
struct scatterlist tx_sg[MAX_SKB_FRAGS + 2];
|
||||
};
|
||||
|
||||
+#if defined(CONFIG_NETMAP) || defined(CONFIG_NETMAP_MODULE)
|
||||
+#include <virtio_netmap.h>
|
||||
+#endif
|
||||
+
|
||||
struct skb_vnet_hdr {
|
||||
union {
|
||||
struct virtio_net_hdr hdr;
|
||||
@@ -124,6 +128,10 @@ static void skb_xmit_done(struct virtqueue *svq)
|
||||
/* Suppress further interrupts. */
|
||||
virtqueue_disable_cb(svq);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (netmap_tx_irq(vi->dev, 0))
|
||||
+ return;
|
||||
+#endif
|
||||
/* We were probably waiting for more output buffers. */
|
||||
netif_wake_queue(vi->dev);
|
||||
}
|
||||
@@ -467,7 +475,16 @@ static int virtnet_poll(struct napi_struct *napi, int budget)
|
||||
struct virtnet_info *vi = container_of(napi, struct virtnet_info, napi);
|
||||
void *buf;
|
||||
unsigned int len, received = 0;
|
||||
+#ifdef DEV_NETMAP
|
||||
+ int work_done = 0;
|
||||
|
||||
+ if (netmap_rx_irq(vi->dev, 0, &work_done)) {
|
||||
+ napi_complete(napi);
|
||||
+ ND("called netmap_rx_irq");
|
||||
+
|
||||
+ return 1;
|
||||
+ }
|
||||
+#endif
|
||||
again:
|
||||
while (received < budget &&
|
||||
(buf = virtqueue_get_buf(vi->rvq, &len)) != NULL) {
|
||||
@@ -638,6 +655,10 @@ static int virtnet_open(struct net_device *dev)
|
||||
{
|
||||
struct virtnet_info *vi = netdev_priv(dev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ virtio_netmap_init_buffers(vi);
|
||||
+ netmap_enable_all_rings(dev);
|
||||
+#endif
|
||||
napi_enable(&vi->napi);
|
||||
|
||||
/* If all buffers were filled by other side before we napi_enabled, we
|
||||
@@ -700,6 +721,9 @@ static int virtnet_close(struct net_device *dev)
|
||||
{
|
||||
struct virtnet_info *vi = netdev_priv(dev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_disable_all_rings(dev);
|
||||
+#endif
|
||||
napi_disable(&vi->napi);
|
||||
|
||||
return 0;
|
||||
@@ -986,6 +1010,10 @@ static int virtnet_probe(struct virtio_device *vdev)
|
||||
goto unregister;
|
||||
}
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ virtio_netmap_attach(vi);
|
||||
+#endif
|
||||
+
|
||||
/* Assume link up if device can't report link status,
|
||||
otherwise get link status from config. */
|
||||
if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_STATUS)) {
|
||||
@@ -1035,6 +1063,9 @@ static void __devexit virtnet_remove(struct virtio_device *vdev)
|
||||
{
|
||||
struct virtnet_info *vi = vdev->priv;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_detach(vi->dev);
|
||||
+#endif
|
||||
/* Stop all the virtqueues. */
|
||||
vdev->config->reset(vdev);
|
||||
|
85
netmap/LINUX/final-patches/diff--virtio_net.c--20626--30300
Normal file
85
netmap/LINUX/final-patches/diff--virtio_net.c--20626--30300
Normal file
@ -0,0 +1,85 @@
|
||||
diff --git a/virtio_net.c b/virtio_net.c
|
||||
index 82dba5a..f217797 100644
|
||||
--- a/virtio_net.c
|
||||
+++ b/virtio_net.c
|
||||
@@ -67,6 +67,10 @@ struct virtnet_info {
|
||||
struct scatterlist tx_sg[MAX_SKB_FRAGS + 2];
|
||||
};
|
||||
|
||||
+#if defined(CONFIG_NETMAP) || defined(CONFIG_NETMAP_MODULE)
|
||||
+#include <virtio_netmap.h>
|
||||
+#endif
|
||||
+
|
||||
struct skb_vnet_hdr {
|
||||
union {
|
||||
struct virtio_net_hdr hdr;
|
||||
@@ -124,6 +128,10 @@ static void skb_xmit_done(struct virtqueue *svq)
|
||||
/* Suppress further interrupts. */
|
||||
virtqueue_disable_cb(svq);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (netmap_tx_irq(vi->dev, 0))
|
||||
+ return;
|
||||
+#endif
|
||||
/* We were probably waiting for more output buffers. */
|
||||
netif_wake_queue(vi->dev);
|
||||
}
|
||||
@@ -481,7 +489,16 @@ static int virtnet_poll(struct napi_struct *napi, int budget)
|
||||
struct virtnet_info *vi = container_of(napi, struct virtnet_info, napi);
|
||||
void *buf;
|
||||
unsigned int len, received = 0;
|
||||
+#ifdef DEV_NETMAP
|
||||
+ int work_done = 0;
|
||||
|
||||
+ if (netmap_rx_irq(vi->dev, 0, &work_done)) {
|
||||
+ napi_complete(napi);
|
||||
+ ND("called netmap_rx_irq");
|
||||
+
|
||||
+ return 1;
|
||||
+ }
|
||||
+#endif
|
||||
again:
|
||||
while (received < budget &&
|
||||
(buf = virtqueue_get_buf(vi->rvq, &len)) != NULL) {
|
||||
@@ -652,6 +669,10 @@ static int virtnet_open(struct net_device *dev)
|
||||
{
|
||||
struct virtnet_info *vi = netdev_priv(dev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ virtio_netmap_init_buffers(vi);
|
||||
+ netmap_enable_all_rings(dev);
|
||||
+#endif
|
||||
virtnet_napi_enable(vi);
|
||||
return 0;
|
||||
}
|
||||
@@ -705,6 +726,9 @@ static int virtnet_close(struct net_device *dev)
|
||||
{
|
||||
struct virtnet_info *vi = netdev_priv(dev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_disable_all_rings(dev);
|
||||
+#endif
|
||||
napi_disable(&vi->napi);
|
||||
|
||||
return 0;
|
||||
@@ -991,6 +1015,10 @@ static int virtnet_probe(struct virtio_device *vdev)
|
||||
goto unregister;
|
||||
}
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ virtio_netmap_attach(vi);
|
||||
+#endif
|
||||
+
|
||||
/* Assume link up if device can't report link status,
|
||||
otherwise get link status from config. */
|
||||
if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_STATUS)) {
|
||||
@@ -1040,6 +1068,9 @@ static void __devexit virtnet_remove(struct virtio_device *vdev)
|
||||
{
|
||||
struct virtnet_info *vi = vdev->priv;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_detach(vi->dev);
|
||||
+#endif
|
||||
/* Stop all the virtqueues. */
|
||||
vdev->config->reset(vdev);
|
||||
|
90
netmap/LINUX/final-patches/diff--virtio_net.c--30300--30500
Normal file
90
netmap/LINUX/final-patches/diff--virtio_net.c--30300--30500
Normal file
@ -0,0 +1,90 @@
|
||||
diff --git a/virtio_net.c b/virtio_net.c
|
||||
index 4880aa8..6329c3a 100644
|
||||
--- a/virtio_net.c
|
||||
+++ b/virtio_net.c
|
||||
@@ -80,6 +80,10 @@ struct virtnet_info {
|
||||
struct scatterlist tx_sg[MAX_SKB_FRAGS + 2];
|
||||
};
|
||||
|
||||
+#if defined(CONFIG_NETMAP) || defined(CONFIG_NETMAP_MODULE)
|
||||
+#include <virtio_netmap.h>
|
||||
+#endif
|
||||
+
|
||||
struct skb_vnet_hdr {
|
||||
union {
|
||||
struct virtio_net_hdr hdr;
|
||||
@@ -137,6 +141,10 @@ static void skb_xmit_done(struct virtqueue *svq)
|
||||
/* Suppress further interrupts. */
|
||||
virtqueue_disable_cb(svq);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (netmap_tx_irq(vi->dev, 0))
|
||||
+ return;
|
||||
+#endif
|
||||
/* We were probably waiting for more output buffers. */
|
||||
netif_wake_queue(vi->dev);
|
||||
}
|
||||
@@ -517,7 +525,16 @@ static int virtnet_poll(struct napi_struct *napi, int budget)
|
||||
struct virtnet_info *vi = container_of(napi, struct virtnet_info, napi);
|
||||
void *buf;
|
||||
unsigned int len, received = 0;
|
||||
+#ifdef DEV_NETMAP
|
||||
+ int work_done = 0;
|
||||
|
||||
+ if (netmap_rx_irq(vi->dev, 0, &work_done)) {
|
||||
+ napi_complete(napi);
|
||||
+ ND("called netmap_rx_irq");
|
||||
+
|
||||
+ return 1;
|
||||
+ }
|
||||
+#endif
|
||||
again:
|
||||
while (received < budget &&
|
||||
(buf = virtqueue_get_buf(vi->rvq, &len)) != NULL) {
|
||||
@@ -727,7 +744,15 @@ static void virtnet_netpoll(struct net_device *dev)
|
||||
static int virtnet_open(struct net_device *dev)
|
||||
{
|
||||
struct virtnet_info *vi = netdev_priv(dev);
|
||||
+#ifdef DEV_NETMAP
|
||||
+ int ok = virtio_netmap_init_buffers(vi);
|
||||
|
||||
+ netmap_enable_all_rings(dev);
|
||||
+ if (ok) {
|
||||
+ virtnet_napi_enable(vi);
|
||||
+ return 0;
|
||||
+ }
|
||||
+#endif
|
||||
/* Make sure we have some buffers: if oom use wq. */
|
||||
if (!try_fill_recv(vi, GFP_KERNEL))
|
||||
queue_delayed_work(system_nrt_wq, &vi->refill, 0);
|
||||
@@ -785,6 +810,9 @@ static int virtnet_close(struct net_device *dev)
|
||||
{
|
||||
struct virtnet_info *vi = netdev_priv(dev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_disable_all_rings(dev);
|
||||
+#endif
|
||||
/* Make sure refill_work doesn't re-enable napi! */
|
||||
cancel_delayed_work_sync(&vi->refill);
|
||||
napi_disable(&vi->napi);
|
||||
@@ -1107,6 +1135,10 @@ static int virtnet_probe(struct virtio_device *vdev)
|
||||
goto unregister;
|
||||
}
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ virtio_netmap_attach(vi);
|
||||
+#endif
|
||||
+
|
||||
/* Assume link up if device can't report link status,
|
||||
otherwise get link status from config. */
|
||||
if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_STATUS)) {
|
||||
@@ -1170,6 +1202,9 @@ static void __devexit virtnet_remove(struct virtio_device *vdev)
|
||||
{
|
||||
struct virtnet_info *vi = vdev->priv;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_detach(vi->dev);
|
||||
+#endif
|
||||
unregister_netdev(vi->dev);
|
||||
|
||||
remove_vq_common(vi);
|
90
netmap/LINUX/final-patches/diff--virtio_net.c--30500--30800
Normal file
90
netmap/LINUX/final-patches/diff--virtio_net.c--30500--30800
Normal file
@ -0,0 +1,90 @@
|
||||
diff --git a/virtio_net.c b/virtio_net.c
|
||||
index f18149a..95e1580 100644
|
||||
--- a/virtio_net.c
|
||||
+++ b/virtio_net.c
|
||||
@@ -90,6 +90,10 @@ struct virtnet_info {
|
||||
struct scatterlist tx_sg[MAX_SKB_FRAGS + 2];
|
||||
};
|
||||
|
||||
+#if defined(CONFIG_NETMAP) || defined(CONFIG_NETMAP_MODULE)
|
||||
+#include <virtio_netmap.h>
|
||||
+#endif
|
||||
+
|
||||
struct skb_vnet_hdr {
|
||||
union {
|
||||
struct virtio_net_hdr hdr;
|
||||
@@ -147,6 +151,10 @@ static void skb_xmit_done(struct virtqueue *svq)
|
||||
/* Suppress further interrupts. */
|
||||
virtqueue_disable_cb(svq);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (netmap_tx_irq(vi->dev, 0))
|
||||
+ return;
|
||||
+#endif
|
||||
/* We were probably waiting for more output buffers. */
|
||||
netif_wake_queue(vi->dev);
|
||||
}
|
||||
@@ -529,7 +537,16 @@ static int virtnet_poll(struct napi_struct *napi, int budget)
|
||||
struct virtnet_info *vi = container_of(napi, struct virtnet_info, napi);
|
||||
void *buf;
|
||||
unsigned int len, received = 0;
|
||||
+#ifdef DEV_NETMAP
|
||||
+ int work_done = 0;
|
||||
|
||||
+ if (netmap_rx_irq(vi->dev, 0, &work_done)) {
|
||||
+ napi_complete(napi);
|
||||
+ ND("called netmap_rx_irq");
|
||||
+
|
||||
+ return 1;
|
||||
+ }
|
||||
+#endif
|
||||
again:
|
||||
while (received < budget &&
|
||||
(buf = virtqueue_get_buf(vi->rvq, &len)) != NULL) {
|
||||
@@ -742,6 +759,15 @@ static void virtnet_netpoll(struct net_device *dev)
|
||||
static int virtnet_open(struct net_device *dev)
|
||||
{
|
||||
struct virtnet_info *vi = netdev_priv(dev);
|
||||
+#ifdef DEV_NETMAP
|
||||
+ int ok = virtio_netmap_init_buffers(vi);
|
||||
+
|
||||
+ netmap_enable_all_rings(dev);
|
||||
+ if (ok) {
|
||||
+ virtnet_napi_enable(vi);
|
||||
+ return 0;
|
||||
+ }
|
||||
+#endif
|
||||
|
||||
/* Make sure we have some buffers: if oom use wq. */
|
||||
if (!try_fill_recv(vi, GFP_KERNEL))
|
||||
@@ -810,6 +836,9 @@ static int virtnet_close(struct net_device *dev)
|
||||
{
|
||||
struct virtnet_info *vi = netdev_priv(dev);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_disable_all_rings(dev);
|
||||
+#endif
|
||||
/* Make sure refill_work doesn't re-enable napi! */
|
||||
cancel_delayed_work_sync(&vi->refill);
|
||||
napi_disable(&vi->napi);
|
||||
@@ -1148,6 +1177,10 @@ static int virtnet_probe(struct virtio_device *vdev)
|
||||
goto unregister;
|
||||
}
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ virtio_netmap_attach(vi);
|
||||
+#endif
|
||||
+
|
||||
/* Assume link up if device can't report link status,
|
||||
otherwise get link status from config. */
|
||||
if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_STATUS)) {
|
||||
@@ -1211,6 +1244,9 @@ static void __devexit virtnet_remove(struct virtio_device *vdev)
|
||||
{
|
||||
struct virtnet_info *vi = vdev->priv;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_detach(vi->dev);
|
||||
+#endif
|
||||
/* Prevent config work handler from accessing the device. */
|
||||
mutex_lock(&vi->config_lock);
|
||||
vi->config_enable = false;
|
91
netmap/LINUX/final-patches/diff--virtio_net.c--30800--30b00
Normal file
91
netmap/LINUX/final-patches/diff--virtio_net.c--30800--30b00
Normal file
@ -0,0 +1,91 @@
|
||||
diff --git a/virtio_net.c b/virtio_net.c
|
||||
index 35c00c5..8aaaa7e 100644
|
||||
--- a/virtio_net.c
|
||||
+++ b/virtio_net.c
|
||||
@@ -132,6 +132,10 @@ struct virtnet_info {
|
||||
struct notifier_block nb;
|
||||
};
|
||||
|
||||
+#if defined(CONFIG_NETMAP) || defined(CONFIG_NETMAP_MODULE)
|
||||
+#include <virtio_netmap.h>
|
||||
+#endif
|
||||
+
|
||||
struct skb_vnet_hdr {
|
||||
union {
|
||||
struct virtio_net_hdr hdr;
|
||||
@@ -211,6 +215,10 @@ static void skb_xmit_done(struct virtqueue *vq)
|
||||
/* Suppress further interrupts. */
|
||||
virtqueue_disable_cb(vq);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (netmap_tx_irq(vi->dev, vq2txq(vq)))
|
||||
+ return;
|
||||
+#endif
|
||||
/* We were probably waiting for more output buffers. */
|
||||
netif_wake_subqueue(vi->dev, vq2txq(vq));
|
||||
}
|
||||
@@ -603,7 +611,16 @@ static int virtnet_poll(struct napi_struct *napi, int budget)
|
||||
struct virtnet_info *vi = rq->vq->vdev->priv;
|
||||
void *buf;
|
||||
unsigned int len, received = 0;
|
||||
+#ifdef DEV_NETMAP
|
||||
+ int work_done = 0;
|
||||
|
||||
+ if (netmap_rx_irq(vi->dev, vq2rxq(rq->vq), &work_done)) {
|
||||
+ napi_complete(napi);
|
||||
+ ND("called netmap_rx_irq");
|
||||
+
|
||||
+ return 1;
|
||||
+ }
|
||||
+#endif
|
||||
again:
|
||||
while (received < budget &&
|
||||
(buf = virtqueue_get_buf(rq->vq, &len)) != NULL) {
|
||||
@@ -635,6 +652,16 @@ static int virtnet_open(struct net_device *dev)
|
||||
{
|
||||
struct virtnet_info *vi = netdev_priv(dev);
|
||||
int i;
|
||||
+#ifdef DEV_NETMAP
|
||||
+ int ok = virtio_netmap_init_buffers(vi);
|
||||
+
|
||||
+ netmap_enable_all_rings(dev);
|
||||
+ if (ok) {
|
||||
+ for (i = 0; i < vi->max_queue_pairs; i++)
|
||||
+ virtnet_napi_enable(&vi->rq[i]);
|
||||
+ return 0;
|
||||
+ }
|
||||
+#endif
|
||||
|
||||
for (i = 0; i < vi->max_queue_pairs; i++) {
|
||||
/* Make sure we have some buffers: if oom use wq. */
|
||||
@@ -909,6 +936,9 @@ static int virtnet_close(struct net_device *dev)
|
||||
struct virtnet_info *vi = netdev_priv(dev);
|
||||
int i;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_disable_all_rings(dev);
|
||||
+#endif
|
||||
/* Make sure refill_work doesn't re-enable napi! */
|
||||
cancel_delayed_work_sync(&vi->refill);
|
||||
|
||||
@@ -1572,6 +1602,10 @@ static int virtnet_probe(struct virtio_device *vdev)
|
||||
goto free_recv_bufs;
|
||||
}
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ virtio_netmap_attach(vi);
|
||||
+#endif
|
||||
+
|
||||
/* Assume link up if device can't report link status,
|
||||
otherwise get link status from config. */
|
||||
if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_STATUS)) {
|
||||
@@ -1618,6 +1652,9 @@ static void virtnet_remove(struct virtio_device *vdev)
|
||||
{
|
||||
struct virtnet_info *vi = vdev->priv;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_detach(vi->dev);
|
||||
+#endif
|
||||
unregister_hotcpu_notifier(&vi->nb);
|
||||
|
||||
/* Prevent config work handler from accessing the device. */
|
91
netmap/LINUX/final-patches/diff--virtio_net.c--30b00--99999
Normal file
91
netmap/LINUX/final-patches/diff--virtio_net.c--30b00--99999
Normal file
@ -0,0 +1,91 @@
|
||||
diff --git a/virtio_net.c b/virtio_net.c
|
||||
index 3d2a90a..ae899a4 100644
|
||||
--- a/virtio_net.c
|
||||
+++ b/virtio_net.c
|
||||
@@ -131,6 +131,10 @@ struct virtnet_info {
|
||||
struct notifier_block nb;
|
||||
};
|
||||
|
||||
+#if defined(CONFIG_NETMAP) || defined(CONFIG_NETMAP_MODULE)
|
||||
+#include <virtio_netmap.h>
|
||||
+#endif
|
||||
+
|
||||
struct skb_vnet_hdr {
|
||||
union {
|
||||
struct virtio_net_hdr hdr;
|
||||
@@ -210,6 +214,10 @@ static void skb_xmit_done(struct virtqueue *vq)
|
||||
/* Suppress further interrupts. */
|
||||
virtqueue_disable_cb(vq);
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (netmap_tx_irq(vi->dev, vq2txq(vq)))
|
||||
+ return;
|
||||
+#endif
|
||||
/* We were probably waiting for more output buffers. */
|
||||
netif_wake_subqueue(vi->dev, vq2txq(vq));
|
||||
}
|
||||
@@ -603,7 +611,16 @@ static int virtnet_poll(struct napi_struct *napi, int budget)
|
||||
struct virtnet_info *vi = rq->vq->vdev->priv;
|
||||
void *buf;
|
||||
unsigned int r, len, received = 0;
|
||||
+#ifdef DEV_NETMAP
|
||||
+ int work_done = 0;
|
||||
|
||||
+ if (netmap_rx_irq(vi->dev, vq2rxq(rq->vq), &work_done)) {
|
||||
+ napi_complete(napi);
|
||||
+ ND("called netmap_rx_irq");
|
||||
+
|
||||
+ return 1;
|
||||
+ }
|
||||
+#endif
|
||||
again:
|
||||
while (received < budget &&
|
||||
(buf = virtqueue_get_buf(rq->vq, &len)) != NULL) {
|
||||
@@ -636,6 +653,16 @@ static int virtnet_open(struct net_device *dev)
|
||||
{
|
||||
struct virtnet_info *vi = netdev_priv(dev);
|
||||
int i;
|
||||
+#ifdef DEV_NETMAP
|
||||
+ int ok = virtio_netmap_init_buffers(vi);
|
||||
+
|
||||
+ netmap_enable_all_rings(dev);
|
||||
+ if (ok) {
|
||||
+ for (i = 0; i < vi->max_queue_pairs; i++)
|
||||
+ virtnet_napi_enable(&vi->rq[i]);
|
||||
+ return 0;
|
||||
+ }
|
||||
+#endif
|
||||
|
||||
for (i = 0; i < vi->max_queue_pairs; i++) {
|
||||
if (i < vi->curr_queue_pairs)
|
||||
@@ -927,6 +954,9 @@ static int virtnet_close(struct net_device *dev)
|
||||
struct virtnet_info *vi = netdev_priv(dev);
|
||||
int i;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_disable_all_rings(dev);
|
||||
+#endif
|
||||
/* Make sure refill_work doesn't re-enable napi! */
|
||||
cancel_delayed_work_sync(&vi->refill);
|
||||
|
||||
@@ -1592,6 +1622,10 @@ static int virtnet_probe(struct virtio_device *vdev)
|
||||
goto free_recv_bufs;
|
||||
}
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ virtio_netmap_attach(vi);
|
||||
+#endif
|
||||
+
|
||||
/* Assume link up if device can't report link status,
|
||||
otherwise get link status from config. */
|
||||
if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_STATUS)) {
|
||||
@@ -1638,6 +1672,9 @@ static void virtnet_remove(struct virtio_device *vdev)
|
||||
{
|
||||
struct virtnet_info *vi = vdev->priv;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ netmap_detach(vi->dev);
|
||||
+#endif
|
||||
unregister_hotcpu_notifier(&vi->nb);
|
||||
|
||||
/* Prevent config work handler from accessing the device. */
|
407
netmap/LINUX/forcedeth_netmap.h
Normal file
407
netmap/LINUX/forcedeth_netmap.h
Normal file
@ -0,0 +1,407 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2014 Luigi Rizzo. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id: forcedeth_netmap.h 10670 2012-02-27 21:15:38Z luigi $
|
||||
*
|
||||
* netmap support for: forcedeth (nfe, linux)
|
||||
* For details on netmap support see ixgbe_netmap.h
|
||||
|
||||
The driver supports ORIGinal and EXtended descriptors through unions.
|
||||
We remove the .orig and .ex suffix for brevity.
|
||||
|
||||
Pointers in the ring (N slots) are
|
||||
first_rx = 0, last_rx = N-1, get_rx = put_rx = 0 at init
|
||||
Following init there is a call to nv_alloc_rx_optimized() which does
|
||||
less_rx = get_rx - 1
|
||||
for (put_rx = 0; put_rx != less_rx; put_rx++)
|
||||
put_rx.flags = LEN | NV_RX2_AVAIL;
|
||||
so it leaves one free slot and put_rx pointing at the end.
|
||||
Basically, get_rx is where new packets arrive, put_rx is where
|
||||
new buffers are added.
|
||||
|
||||
The rx_intr aka nv_rx_process_optimized() scans
|
||||
while (get_rx != put_rx && !(get_rx.flags & NV_RX2_AVAIL)) {
|
||||
...
|
||||
get_rx++
|
||||
}
|
||||
followed by a nv_alloc_rx_optimized().
|
||||
This makes sure that there is always a free slot.
|
||||
|
||||
*/
|
||||
|
||||
#include <bsd_glue.h>
|
||||
#include <net/netmap.h>
|
||||
#include <netmap/netmap_kern.h>
|
||||
#define SOFTC_T fe_priv
|
||||
|
||||
|
||||
/*
|
||||
* Register/unregister. We are already under netmap lock.
|
||||
* only called on the first register or the last unregister.
|
||||
* The "forcedeth" driver is poorly written, the reinit routine
|
||||
* is replicated multiple times and one way to achieve it is to
|
||||
* nv_change_mtu twice above ETH_DATA_LEN.
|
||||
*/
|
||||
static int
|
||||
forcedeth_netmap_reg(struct netmap_adapter *na, int onoff)
|
||||
{
|
||||
struct ifnet *ifp = na->ifp;
|
||||
struct SOFTC_T *np = netdev_priv(ifp);
|
||||
u8 __iomem *base = get_hwbase(ifp);
|
||||
|
||||
// first half of nv_change_mtu() - down
|
||||
nv_disable_irq(ifp);
|
||||
nv_napi_disable(ifp);
|
||||
netif_tx_lock_bh(ifp);
|
||||
netif_addr_lock(ifp);
|
||||
spin_lock(&np->lock);
|
||||
/* stop engines */
|
||||
nv_stop_rxtx(ifp);
|
||||
nv_txrx_reset(ifp);
|
||||
/* drain rx queue */
|
||||
nv_drain_rxtx(ifp);
|
||||
|
||||
if (onoff) {
|
||||
nm_set_native_flags(na);
|
||||
} else {
|
||||
nm_clear_native_flags(na);
|
||||
}
|
||||
// second half of nv_change_mtu() -- up
|
||||
if (nv_init_ring(ifp)) {
|
||||
if (!np->in_shutdown)
|
||||
mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
|
||||
}
|
||||
/* reinit nic view of the rx queue */
|
||||
writel(np->rx_buf_sz, base + NvRegOffloadConfig);
|
||||
setup_hw_rings(ifp, NV_SETUP_RX_RING | NV_SETUP_TX_RING);
|
||||
writel(((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT),
|
||||
base + NvRegRingSizes);
|
||||
pci_push(base);
|
||||
writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(ifp) + NvRegTxRxControl);
|
||||
pci_push(base);
|
||||
/* restart rx engine */
|
||||
nv_start_rxtx(ifp);
|
||||
spin_unlock(&np->lock);
|
||||
netif_addr_unlock(ifp);
|
||||
netif_tx_unlock_bh(ifp);
|
||||
nv_napi_enable(ifp);
|
||||
nv_enable_irq(ifp);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Reconcile kernel and user view of the transmit ring.
|
||||
*/
|
||||
static int
|
||||
forcedeth_netmap_txsync(struct netmap_kring *kring, int flags)
|
||||
{
|
||||
struct netmap_adapter *na = kring->na;
|
||||
struct ifnet *ifp = na->ifp;
|
||||
struct netmap_ring *ring = kring->ring;
|
||||
u_int nm_i; /* index into the netmap ring */
|
||||
u_int nic_i; /* index into the NIC ring */
|
||||
u_int n;
|
||||
u_int const lim = kring->nkr_num_slots - 1;
|
||||
u_int const head = kring->rhead;
|
||||
|
||||
/* device-specific */
|
||||
struct SOFTC_T *np = netdev_priv(ifp);
|
||||
struct ring_desc_ex *txr = np->tx_ring.ex;
|
||||
uint32_t lastpkt = (np->desc_ver == DESC_VER_1 ? NV_TX_LASTPACKET : NV_TX2_LASTPACKET);
|
||||
u_int k;
|
||||
|
||||
/*
|
||||
* First part: process new packets to send.
|
||||
*/
|
||||
|
||||
if (!netif_carrier_ok(ifp)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
nm_i = kring->nr_hwcur;
|
||||
if (nm_i != head) { /* we have new packets to send */
|
||||
nic_i = np->put_tx.ex - txr; // NIC pointer
|
||||
for (n = 0; nm_i != head; n++) {
|
||||
struct netmap_slot *slot = &ring->slot[nm_i];
|
||||
u_int len = slot->len;
|
||||
uint64_t paddr;
|
||||
void *addr = PNMB(slot, &paddr);
|
||||
|
||||
/* device-specific */
|
||||
struct ring_desc_ex *put_tx = txr + nic_i;
|
||||
// XXX check who needs lastpkt
|
||||
int cmd = (len - 1) | NV_TX2_VALID | lastpkt;
|
||||
|
||||
NM_CHECK_ADDR_LEN(addr, len);
|
||||
|
||||
if (slot->flags & NS_BUF_CHANGED) {
|
||||
/* buffer has changed, reload map */
|
||||
// netmap_reload_map(pdev, DMA_TO_DEVICE, old_paddr, addr);
|
||||
}
|
||||
slot->flags &= ~(NS_REPORT | NS_BUF_CHANGED);
|
||||
|
||||
/* Fill the slot in the NIC ring. */
|
||||
put_tx->bufhigh = htole32(dma_high(paddr));
|
||||
put_tx->buflow = htole32(dma_low(paddr));
|
||||
put_tx->flaglen = htole32(cmd);
|
||||
put_tx->txvlan = 0;
|
||||
nm_i = nm_next(nm_i, lim);
|
||||
nic_i = nm_next(nic_i, lim);
|
||||
}
|
||||
np->put_tx.ex = txr + nic_i;
|
||||
kring->nr_hwcur = head;
|
||||
wmb(); /* synchronize writes to the NIC ring */
|
||||
/* restart tx unit where is the new index ? */
|
||||
writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits,
|
||||
get_hwbase(ifp) + NvRegTxRxControl);
|
||||
}
|
||||
|
||||
/*
|
||||
* Second part: reclaim buffers for completed transmissions
|
||||
*/
|
||||
/* Sync the TX descriptor list */
|
||||
rmb();
|
||||
nic_i = np->get_tx.ex - txr;
|
||||
k = np->put_tx.ex - txr;
|
||||
if (nic_i != k) {
|
||||
for (n = 0; nic_i != k; n++) {
|
||||
uint32_t cmdstat = le32toh(txr[nic_i].flaglen);
|
||||
if (cmdstat & NV_TX2_VALID)
|
||||
break;
|
||||
if (++nic_i == np->tx_ring_size)
|
||||
nic_i = 0;
|
||||
}
|
||||
if (n > 0) {
|
||||
np->get_tx.ex = txr + nic_i;
|
||||
kring->nr_hwtail = nm_prev(netmap_idx_n2k(kring, nic_i), lim);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
nm_txsync_finalize(kring);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Reconcile kernel and user view of the receive ring.
|
||||
*/
|
||||
static int
|
||||
forcedeth_netmap_rxsync(struct netmap_kring *kring, int flags)
|
||||
{
|
||||
struct netmap_adapter *na = kring->na;
|
||||
struct ifnet *ifp = na->ifp;
|
||||
struct netmap_ring *ring = kring->ring;
|
||||
u_int nm_i; /* index into the netmap ring */
|
||||
u_int nic_i; /* index into the NIC ring */
|
||||
u_int n;
|
||||
u_int const lim = kring->nkr_num_slots - 1;
|
||||
u_int const head = nm_rxsync_prologue(kring);
|
||||
int force_update = (flags & NAF_FORCE_READ) || kring->nr_kflags & NKR_PENDINTR;
|
||||
|
||||
/* device-specific */
|
||||
struct SOFTC_T *np = netdev_priv(ifp);
|
||||
struct ring_desc_ex *rxr = np->rx_ring.ex;
|
||||
u_int refill; // refill position
|
||||
|
||||
if (head > lim)
|
||||
return netmap_ring_reinit(kring);
|
||||
|
||||
/*
|
||||
* First part: import newly received packets.
|
||||
*/
|
||||
rmb();
|
||||
if (netmap_no_pendintr || force_update) {
|
||||
uint16_t slot_flags = kring->nkr_slot_flags;
|
||||
|
||||
nic_i = np->get_rx.ex - rxr; /* next pkt to check */
|
||||
/* put_rx is the refill position, one before nr_hwcur.
|
||||
* This slot is not available
|
||||
*/
|
||||
refill = np->put_rx.ex - rxr; /* refill position */
|
||||
nm_i = netmap_idx_n2k(kring, nic_i);
|
||||
|
||||
while (nic_i != refill) {
|
||||
uint32_t statlen = le32toh(rxr[nic_i].flaglen);
|
||||
|
||||
if (statlen & NV_RX2_AVAIL) /* still owned by the NIC */
|
||||
break;
|
||||
ring->slot[nm_i].len = statlen & LEN_MASK_V2; // XXX crc?
|
||||
ring->slot[nm_i].flags = slot_flags;
|
||||
// ifp->stats.rx_packets++;
|
||||
nm_i = nm_next(nm_i, lim);
|
||||
nic_i = nm_next(nic_i, lim);
|
||||
}
|
||||
np->get_rx.ex = rxr + nic_i;
|
||||
kring->nr_hwtail = nm_i;
|
||||
}
|
||||
|
||||
/*
|
||||
* Second part: skip past packets that userspace has released.
|
||||
*/
|
||||
nm_i = kring->nr_hwcur; // refill is one before nic_i
|
||||
if (nm_i != head) {
|
||||
nic_i = netmap_idx_k2n(kring, nm_i);
|
||||
refill = np->put_rx.ex - rxr; /* refill position */
|
||||
|
||||
for (n = 0; nm_i != head; n++) {
|
||||
struct netmap_slot *slot = &ring->slot[nm_i];
|
||||
uint64_t paddr;
|
||||
void *addr = PNMB(slot, &paddr);
|
||||
|
||||
struct ring_desc_ex *desc = rxr + nic_i;
|
||||
|
||||
if (addr == netmap_buffer_base) /* bad buf */
|
||||
goto ring_reset;
|
||||
|
||||
if (slot->flags & NS_BUF_CHANGED) {
|
||||
/* buffer has changed, reload map */
|
||||
// netmap_reload_map(pdev, DMA_TO_DEVICE, old_paddr, addr);
|
||||
slot->flags &= ~NS_BUF_CHANGED;
|
||||
}
|
||||
|
||||
desc->flaglen = htole32(NETMAP_BUF_SIZE);
|
||||
desc->bufhigh = htole32(dma_high(paddr));
|
||||
desc->buflow = htole32(dma_low(paddr));
|
||||
// enable the previous buffer
|
||||
rxr[refill].flaglen |= htole32(NV_RX2_AVAIL);
|
||||
refill = nm_next(refill, lim);
|
||||
nm_i = nm_next(nm_i, lim);
|
||||
nic_i = nm_next(nic_i, lim);
|
||||
}
|
||||
kring->nr_hwcur = head;
|
||||
np->put_rx.ex = rxr + refill;
|
||||
/* Flush the RX DMA ring */
|
||||
wmb();
|
||||
}
|
||||
|
||||
/* tell userspace that there are might be new packets */
|
||||
nm_rxsync_finalize(kring);
|
||||
|
||||
return 0;
|
||||
|
||||
ring_reset:
|
||||
return netmap_ring_reinit(kring);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Additional routines to init the tx and rx rings.
|
||||
* In other drivers we do that inline in the main code.
|
||||
*/
|
||||
static int
|
||||
forcedeth_netmap_tx_init(struct SOFTC_T *np)
|
||||
{
|
||||
struct ring_desc_ex *desc;
|
||||
int i, n;
|
||||
struct netmap_adapter *na = NA(np->dev);
|
||||
struct netmap_slot *slot;
|
||||
|
||||
if (!na || !(na->na_flags & NAF_NATIVE_ON)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
slot = netmap_reset(na, NR_TX, 0, 0);
|
||||
/* slot is NULL if we are not in netmap mode */
|
||||
if (!slot)
|
||||
return 0;
|
||||
/* in netmap mode, overwrite addresses and maps */
|
||||
//txd = np->rl_ldata.rl_tx_desc;
|
||||
desc = np->tx_ring.ex;
|
||||
n = np->tx_ring_size;
|
||||
|
||||
/* l points in the netmap ring, i points in the NIC ring */
|
||||
for (i = 0; i < n; i++) {
|
||||
int l = netmap_idx_n2k(&na->tx_rings[0], i);
|
||||
uint64_t paddr;
|
||||
PNMB(slot + l, &paddr);
|
||||
desc[i].flaglen = 0;
|
||||
desc[i].bufhigh = htole32(dma_high(paddr));
|
||||
desc[i].buflow = htole32(dma_low(paddr));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
forcedeth_netmap_rx_init(struct SOFTC_T *np)
|
||||
{
|
||||
struct netmap_adapter *na = NA(np->dev);
|
||||
struct netmap_slot *slot = netmap_reset(na, NR_RX, 0, 0);
|
||||
struct ring_desc_ex *desc = np->rx_ring.ex;
|
||||
uint32_t cmdstat;
|
||||
int i, lim;
|
||||
|
||||
if (!slot)
|
||||
return 0;
|
||||
/*
|
||||
* Do not release the slots owned by userspace,
|
||||
* and also keep one empty.
|
||||
*/
|
||||
lim = np->rx_ring_size - 1 - nm_kr_rxspace(&na->rx_rings[0]);
|
||||
for (i = 0; i < np->rx_ring_size; i++) {
|
||||
void *addr;
|
||||
uint64_t paddr;
|
||||
int l = netmap_idx_n2k(&na->rx_rings[0], i);
|
||||
|
||||
addr = PNMB(slot + l, &paddr);
|
||||
netmap_reload_map(np->rl_ldata.rl_rx_mtag,
|
||||
np->rl_ldata.rl_rx_desc[i].rx_dmamap, addr);
|
||||
desc[i].bufhigh = htole32(dma_high(paddr));
|
||||
desc[i].buflow = htole32(dma_low(paddr));
|
||||
cmdstat = NETMAP_BUF_SIZE;
|
||||
if (i < lim)
|
||||
cmdstat |= NV_RX2_AVAIL;
|
||||
desc[i].flaglen = htole32(cmdstat);
|
||||
}
|
||||
// XXX ring end anywhere ?
|
||||
np->get_rx.ex = desc;
|
||||
np->put_rx.ex = desc + lim;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
forcedeth_netmap_attach(struct SOFTC_T *np)
|
||||
{
|
||||
struct netmap_adapter na;
|
||||
|
||||
bzero(&na, sizeof(na));
|
||||
|
||||
na.ifp = np->dev;
|
||||
na.num_tx_desc = np->tx_ring_size;
|
||||
na.num_rx_desc = np->tx_ring_size;
|
||||
na.nm_txsync = forcedeth_netmap_txsync;
|
||||
na.nm_rxsync = forcedeth_netmap_rxsync;
|
||||
na.nm_register = forcedeth_netmap_reg;
|
||||
na.num_tx_rings = na.num_rx_rings = 1;
|
||||
netmap_attach(&na);
|
||||
}
|
||||
|
||||
/* end of file */
|
352
netmap/LINUX/if_e1000_netmap.h
Normal file
352
netmap/LINUX/if_e1000_netmap.h
Normal file
@ -0,0 +1,352 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2014 Gaetano Catalli, Luigi Rizzo. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id: if_e1000_netmap.h 10878 2012-04-12 22:28:48Z luigi $
|
||||
*
|
||||
* netmap support for: e1000 (linux version)
|
||||
* For details on netmap support please see ixgbe_netmap.h
|
||||
*/
|
||||
|
||||
|
||||
#include <bsd_glue.h>
|
||||
#include <net/netmap.h>
|
||||
#include <netmap/netmap_kern.h>
|
||||
|
||||
#define SOFTC_T e1000_adapter
|
||||
|
||||
|
||||
/*
|
||||
* Register/unregister. We are already under netmap lock.
|
||||
*/
|
||||
static int
|
||||
e1000_netmap_reg(struct netmap_adapter *na, int onoff)
|
||||
{
|
||||
struct ifnet *ifp = na->ifp;
|
||||
struct SOFTC_T *adapter = netdev_priv(ifp);
|
||||
|
||||
/* protect against other reinit */
|
||||
while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
|
||||
usleep_range(1000, 2000);
|
||||
|
||||
rtnl_lock();
|
||||
if (netif_running(adapter->netdev))
|
||||
e1000_down(adapter);
|
||||
|
||||
/* enable or disable flags and callbacks in na and ifp */
|
||||
if (onoff) {
|
||||
nm_set_native_flags(na);
|
||||
} else {
|
||||
nm_clear_native_flags(na);
|
||||
}
|
||||
if (netif_running(adapter->netdev))
|
||||
e1000_up(adapter);
|
||||
else
|
||||
e1000_reset(adapter);
|
||||
|
||||
rtnl_unlock();
|
||||
clear_bit(__E1000_RESETTING, &adapter->flags);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Reconcile kernel and user view of the transmit ring.
|
||||
*/
|
||||
static int
|
||||
e1000_netmap_txsync(struct netmap_kring *kring, int flags)
|
||||
{
|
||||
struct netmap_adapter *na = kring->na;
|
||||
struct ifnet *ifp = na->ifp;
|
||||
struct netmap_ring *ring = kring->ring;
|
||||
u_int ring_nr = kring->ring_id;
|
||||
u_int nm_i; /* index into the netmap ring */
|
||||
u_int nic_i; /* index into the NIC ring */
|
||||
u_int n;
|
||||
u_int const lim = kring->nkr_num_slots - 1;
|
||||
u_int const head = kring->rhead;
|
||||
/* generate an interrupt approximately every half ring */
|
||||
u_int report_frequency = kring->nkr_num_slots >> 1;
|
||||
|
||||
/* device-specific */
|
||||
struct SOFTC_T *adapter = netdev_priv(ifp);
|
||||
struct e1000_tx_ring* txr = &adapter->tx_ring[ring_nr];
|
||||
|
||||
rmb();
|
||||
/*
|
||||
* First part: process new packets to send.
|
||||
*/
|
||||
|
||||
if (!netif_carrier_ok(ifp)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
nm_i = kring->nr_hwcur;
|
||||
if (nm_i != head) { /* we have new packets to send */
|
||||
nic_i = netmap_idx_k2n(kring, nm_i);
|
||||
for (n = 0; nm_i != head; n++) {
|
||||
struct netmap_slot *slot = &ring->slot[nm_i];
|
||||
u_int len = slot->len;
|
||||
uint64_t paddr;
|
||||
void *addr = PNMB(slot, &paddr);
|
||||
|
||||
/* device-specific */
|
||||
struct e1000_tx_desc *curr = E1000_TX_DESC(*txr, nic_i);
|
||||
int flags = (slot->flags & NS_REPORT ||
|
||||
nic_i == 0 || nic_i == report_frequency) ?
|
||||
E1000_TXD_CMD_RS : 0;
|
||||
|
||||
NM_CHECK_ADDR_LEN(addr, len);
|
||||
|
||||
if (slot->flags & NS_BUF_CHANGED) {
|
||||
/* buffer has changed, reload map */
|
||||
// netmap_reload_map(pdev, DMA_TO_DEVICE, old_addr, paddr);
|
||||
curr->buffer_addr = htole64(paddr);
|
||||
}
|
||||
slot->flags &= ~(NS_REPORT | NS_BUF_CHANGED);
|
||||
|
||||
/* Fill the slot in the NIC ring. */
|
||||
curr->upper.data = 0;
|
||||
curr->lower.data = htole32(adapter->txd_cmd |
|
||||
len | flags |
|
||||
E1000_TXD_CMD_EOP | E1000_TXD_CMD_IFCS);
|
||||
nm_i = nm_next(nm_i, lim);
|
||||
nic_i = nm_next(nic_i, lim);
|
||||
}
|
||||
kring->nr_hwcur = head;
|
||||
|
||||
wmb(); /* synchronize writes to the NIC ring */
|
||||
txr->next_to_use = nic_i; /* XXX what for ? */
|
||||
/* (re)start the tx unit up to slot nic_i (excluded) */
|
||||
writel(nic_i, adapter->hw.hw_addr + txr->tdt);
|
||||
mmiowb(); // XXX where do we need this ?
|
||||
}
|
||||
|
||||
/*
|
||||
* Second part: reclaim buffers for completed transmissions.
|
||||
*/
|
||||
if (flags & NAF_FORCE_RECLAIM || nm_kr_txempty(kring)) {
|
||||
/* record completed transmissions using TDH */
|
||||
nic_i = readl(adapter->hw.hw_addr + txr->tdh);
|
||||
if (nic_i >= kring->nkr_num_slots) { /* XXX can it happen ? */
|
||||
D("TDH wrap %d", nic_i);
|
||||
nic_i -= kring->nkr_num_slots;
|
||||
}
|
||||
txr->next_to_clean = nic_i;
|
||||
kring->nr_hwtail = nm_prev(netmap_idx_n2k(kring, nic_i), lim);
|
||||
}
|
||||
out:
|
||||
nm_txsync_finalize(kring);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Reconcile kernel and user view of the receive ring.
|
||||
*/
|
||||
static int
|
||||
e1000_netmap_rxsync(struct netmap_kring *kring, int flags)
|
||||
{
|
||||
struct netmap_adapter *na = kring->na;
|
||||
struct ifnet *ifp = na->ifp;
|
||||
struct netmap_ring *ring = kring->ring;
|
||||
u_int ring_nr = kring->ring_id;
|
||||
u_int nm_i; /* index into the netmap ring */
|
||||
u_int nic_i; /* index into the NIC ring */
|
||||
u_int n;
|
||||
u_int const lim = kring->nkr_num_slots - 1;
|
||||
u_int const head = nm_rxsync_prologue(kring);
|
||||
int force_update = (flags & NAF_FORCE_READ) || kring->nr_kflags & NKR_PENDINTR;
|
||||
|
||||
/* device-specific */
|
||||
struct SOFTC_T *adapter = netdev_priv(ifp);
|
||||
struct e1000_rx_ring *rxr = &adapter->rx_ring[ring_nr];
|
||||
|
||||
if (!netif_carrier_ok(ifp)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (head > lim)
|
||||
return netmap_ring_reinit(kring);
|
||||
|
||||
rmb();
|
||||
|
||||
/*
|
||||
* First part: import newly received packets.
|
||||
*/
|
||||
if (netmap_no_pendintr || force_update) {
|
||||
uint16_t slot_flags = kring->nkr_slot_flags;
|
||||
|
||||
nic_i = rxr->next_to_clean;
|
||||
nm_i = netmap_idx_n2k(kring, nic_i);
|
||||
|
||||
for (n = 0; ; n++) {
|
||||
struct e1000_rx_desc *curr = E1000_RX_DESC(*rxr, nic_i);
|
||||
uint32_t staterr = le32toh(curr->status);
|
||||
|
||||
if ((staterr & E1000_RXD_STAT_DD) == 0)
|
||||
break;
|
||||
ring->slot[nm_i].len = le16toh(curr->length) - 4;
|
||||
ring->slot[nm_i].flags = slot_flags;
|
||||
nm_i = nm_next(nm_i, lim);
|
||||
nic_i = nm_next(nic_i, lim);
|
||||
}
|
||||
if (n) { /* update the state variables */
|
||||
rxr->next_to_clean = nic_i;
|
||||
kring->nr_hwtail = nm_i;
|
||||
}
|
||||
kring->nr_kflags &= ~NKR_PENDINTR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Second part: skip past packets that userspace has released.
|
||||
*/
|
||||
nm_i = kring->nr_hwcur;
|
||||
if (nm_i != head) {
|
||||
nic_i = netmap_idx_k2n(kring, nm_i);
|
||||
for (n = 0; nm_i != head; n++) {
|
||||
struct netmap_slot *slot = &ring->slot[nm_i];
|
||||
uint64_t paddr;
|
||||
void *addr = PNMB(slot, &paddr);
|
||||
struct e1000_rx_desc *curr = E1000_RX_DESC(*rxr, nic_i);
|
||||
|
||||
if (addr == netmap_buffer_base) /* bad buf */
|
||||
goto ring_reset;
|
||||
if (slot->flags & NS_BUF_CHANGED) {
|
||||
// netmap_reload_map(...)
|
||||
curr->buffer_addr = htole64(paddr);
|
||||
slot->flags &= ~NS_BUF_CHANGED;
|
||||
}
|
||||
curr->status = 0;
|
||||
nm_i = nm_next(nm_i, lim);
|
||||
nic_i = nm_next(nic_i, lim);
|
||||
}
|
||||
kring->nr_hwcur = head;
|
||||
rxr->next_to_use = nic_i; // XXX not really used
|
||||
wmb();
|
||||
/*
|
||||
* IMPORTANT: we must leave one free slot in the ring,
|
||||
* so move nic_i back by one unit
|
||||
*/
|
||||
nic_i = nm_prev(nic_i, lim);
|
||||
writel(nic_i, adapter->hw.hw_addr + rxr->rdt);
|
||||
}
|
||||
out:
|
||||
/* tell userspace that there might be new packets */
|
||||
nm_rxsync_finalize(kring);
|
||||
|
||||
return 0;
|
||||
|
||||
ring_reset:
|
||||
return netmap_ring_reinit(kring);
|
||||
}
|
||||
|
||||
|
||||
/* diagnostic routine to catch errors */
|
||||
static void e1000_no_rx_alloc(struct SOFTC_T *adapter,
|
||||
struct e1000_rx_ring *rxr, int cleaned_count)
|
||||
{
|
||||
D("e1000->alloc_rx_buf should not be called");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Make the tx and rx rings point to the netmap buffers.
|
||||
*/
|
||||
static int e1000_netmap_init_buffers(struct SOFTC_T *adapter)
|
||||
{
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
struct ifnet *ifp = adapter->netdev;
|
||||
struct netmap_adapter* na = NA(ifp);
|
||||
struct netmap_slot* slot;
|
||||
struct e1000_tx_ring* txr = &adapter->tx_ring[0];
|
||||
unsigned int i, r, si;
|
||||
uint64_t paddr;
|
||||
|
||||
if (!na || !(na->na_flags & NAF_NATIVE_ON)) {
|
||||
return 0;
|
||||
}
|
||||
adapter->alloc_rx_buf = e1000_no_rx_alloc;
|
||||
for (r = 0; r < na->num_rx_rings; r++) {
|
||||
struct e1000_rx_ring *rxr;
|
||||
slot = netmap_reset(na, NR_RX, r, 0);
|
||||
if (!slot) {
|
||||
D("strange, null netmap ring %d", r);
|
||||
return 0;
|
||||
}
|
||||
rxr = &adapter->rx_ring[r];
|
||||
|
||||
for (i = 0; i < rxr->count; i++) {
|
||||
// XXX the skb check and cleanup can go away
|
||||
struct e1000_buffer *bi = &rxr->buffer_info[i];
|
||||
si = netmap_idx_n2k(&na->rx_rings[r], i);
|
||||
PNMB(slot + si, &paddr);
|
||||
if (bi->skb)
|
||||
D("rx buf %d was set", i);
|
||||
bi->skb = NULL;
|
||||
// netmap_load_map(...)
|
||||
E1000_RX_DESC(*rxr, i)->buffer_addr = htole64(paddr);
|
||||
}
|
||||
|
||||
rxr->next_to_use = 0;
|
||||
/* preserve buffers already made available to clients */
|
||||
i = rxr->count - 1 - nm_kr_rxspace(&na->rx_rings[0]);
|
||||
if (i < 0) // XXX something wrong here, can it really happen ?
|
||||
i += rxr->count;
|
||||
D("i now is %d", i);
|
||||
wmb(); /* Force memory writes to complete */
|
||||
writel(i, hw->hw_addr + rxr->rdt);
|
||||
}
|
||||
/* now initialize the tx ring(s) */
|
||||
slot = netmap_reset(na, NR_TX, 0, 0);
|
||||
for (i = 0; i < na->num_tx_desc; i++) {
|
||||
si = netmap_idx_n2k(&na->tx_rings[0], i);
|
||||
PNMB(slot + si, &paddr);
|
||||
// netmap_load_map(...)
|
||||
E1000_TX_DESC(*txr, i)->buffer_addr = htole64(paddr);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
e1000_netmap_attach(struct SOFTC_T *adapter)
|
||||
{
|
||||
struct netmap_adapter na;
|
||||
|
||||
bzero(&na, sizeof(na));
|
||||
|
||||
na.ifp = adapter->netdev;
|
||||
na.num_tx_desc = adapter->tx_ring[0].count;
|
||||
na.num_rx_desc = adapter->rx_ring[0].count;
|
||||
na.nm_register = e1000_netmap_reg;
|
||||
na.nm_txsync = e1000_netmap_txsync;
|
||||
na.nm_rxsync = e1000_netmap_rxsync;
|
||||
na.num_tx_rings = na.num_rx_rings = 1;
|
||||
netmap_attach(&na);
|
||||
}
|
||||
|
||||
/* end of file */
|
377
netmap/LINUX/if_e1000e_netmap.h
Normal file
377
netmap/LINUX/if_e1000e_netmap.h
Normal file
@ -0,0 +1,377 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2014 Gaetano Catalli, Luigi Rizzo. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id: if_e1000e_netmap.h 10670 2012-02-27 21:15:38Z luigi $
|
||||
*
|
||||
* netmap support for: e1000e (linux version)
|
||||
* For details on netmap support please see ixgbe_netmap.h
|
||||
* The driver supports 1 TX and 1 RX ring. Single lock.
|
||||
* tx buffer address only written on change.
|
||||
* Apparently the driver uses extended descriptors on rx from 3.2.32
|
||||
* Rx Crc stripping ?
|
||||
*/
|
||||
|
||||
|
||||
#include <bsd_glue.h>
|
||||
#include <net/netmap.h>
|
||||
#include <netmap/netmap_kern.h>
|
||||
|
||||
#define SOFTC_T e1000_adapter
|
||||
|
||||
/*
|
||||
* Adaptation to different versions of the driver.
|
||||
*/
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
|
||||
#warning this driver uses extended descriptors
|
||||
#define NM_E1K_RX_DESC_T union e1000_rx_desc_extended
|
||||
#define NM_E1R_RX_STATUS wb.upper.status_error
|
||||
#define NM_E1R_RX_LENGTH wb.upper.length
|
||||
#define NM_E1R_RX_BUFADDR read.buffer_addr
|
||||
#else
|
||||
#warning this driver uses regular descriptors
|
||||
#define E1000_RX_DESC_EXT E1000_RX_DESC // XXX workaround
|
||||
#define NM_E1K_RX_DESC_T struct e1000_rx_desc
|
||||
#define NM_E1R_RX_STATUS status
|
||||
#define NM_E1R_RX_BUFADDR buffer_addr
|
||||
#define NM_E1R_RX_LENGTH length
|
||||
#endif /* up to 3.2.x */
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
|
||||
#define NM_WR_TX_TAIL(_x) writel(_x, txr->tail) // XXX tx_ring
|
||||
#define NM_WR_RX_TAIL(_x) writel(_x, rxr->tail) // XXX rx_ring
|
||||
#define NM_RD_TX_HEAD() readl(txr->head)
|
||||
#else
|
||||
#define NM_WR_TX_TAIL(_x) writel(_x, adapter->hw.hw_addr + txr->tail)
|
||||
#define NM_WR_RX_TAIL(_x) writel(_x, adapter->hw.hw_addr + rxr->tail)
|
||||
#define NM_RD_TX_HEAD() readl(adapter->hw.hw_addr + txr->head)
|
||||
#endif /* < 3.4.0 */
|
||||
|
||||
|
||||
/*
|
||||
* Register/unregister. We are already under netmap lock.
|
||||
*/
|
||||
static int
|
||||
e1000_netmap_reg(struct netmap_adapter *na, int onoff)
|
||||
{
|
||||
struct ifnet *ifp = na->ifp;
|
||||
struct SOFTC_T *adapter = netdev_priv(ifp);
|
||||
|
||||
/* protect against other reinit */
|
||||
while (test_and_set_bit(__E1000_RESETTING, &adapter->state))
|
||||
usleep_range(1000, 2000);
|
||||
|
||||
rtnl_lock();
|
||||
if (netif_running(adapter->netdev))
|
||||
e1000e_down(adapter);
|
||||
|
||||
/* enable or disable flags and callbacks in na and ifp */
|
||||
if (onoff) {
|
||||
nm_set_native_flags(na);
|
||||
} else {
|
||||
nm_clear_native_flags(na);
|
||||
}
|
||||
|
||||
if (netif_running(adapter->netdev))
|
||||
e1000e_up(adapter);
|
||||
else
|
||||
e1000e_reset(adapter); // XXX is it needed ?
|
||||
|
||||
rtnl_unlock();
|
||||
|
||||
clear_bit(__E1000_RESETTING, &adapter->state);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Reconcile kernel and user view of the transmit ring.
|
||||
*/
|
||||
static int
|
||||
e1000_netmap_txsync(struct netmap_kring *kring, int flags)
|
||||
{
|
||||
struct netmap_adapter *na = kring->na;
|
||||
struct ifnet *ifp = na->ifp;
|
||||
struct netmap_ring *ring = kring->ring;
|
||||
u_int ring_nr = kring->ring_id;
|
||||
u_int nm_i; /* index into the netmap ring */
|
||||
u_int nic_i; /* index into the NIC ring */
|
||||
u_int n;
|
||||
u_int const lim = kring->nkr_num_slots - 1;
|
||||
u_int const head = kring->rhead;
|
||||
/* generate an interrupt approximately every half ring */
|
||||
u_int report_frequency = kring->nkr_num_slots >> 1;
|
||||
|
||||
/* device-specific */
|
||||
struct SOFTC_T *adapter = netdev_priv(ifp);
|
||||
struct e1000_ring* txr = &adapter->tx_ring[ring_nr];
|
||||
|
||||
rmb();
|
||||
/*
|
||||
* First part: process new packets to send.
|
||||
*/
|
||||
|
||||
if (!netif_carrier_ok(ifp)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
nm_i = kring->nr_hwcur;
|
||||
if (nm_i != head) { /* we have new packets to send */
|
||||
nic_i = netmap_idx_k2n(kring, nm_i);
|
||||
for (n = 0; nm_i != head; n++) {
|
||||
struct netmap_slot *slot = &ring->slot[nm_i];
|
||||
u_int len = slot->len;
|
||||
uint64_t paddr;
|
||||
void *addr = PNMB(slot, &paddr);
|
||||
|
||||
/* device-specific */
|
||||
struct e1000_tx_desc *curr = E1000_TX_DESC(*txr, nic_i);
|
||||
int flags = (slot->flags & NS_REPORT ||
|
||||
nic_i == 0 || nic_i == report_frequency) ?
|
||||
E1000_TXD_CMD_RS : 0;
|
||||
|
||||
NM_CHECK_ADDR_LEN(addr, len);
|
||||
|
||||
if (slot->flags & NS_BUF_CHANGED) {
|
||||
/* buffer has changed, reload map */
|
||||
// netmap_reload_map(pdev, DMA_TO_DEVICE, old_paddr, addr)
|
||||
curr->buffer_addr = htole64(paddr);
|
||||
}
|
||||
slot->flags &= ~(NS_REPORT | NS_BUF_CHANGED);
|
||||
|
||||
/* Fill the slot in the NIC ring. */
|
||||
curr->upper.data = 0;
|
||||
curr->lower.data = htole32(adapter->txd_cmd | len | flags |
|
||||
E1000_TXD_CMD_EOP);
|
||||
nm_i = nm_next(nm_i, lim);
|
||||
nic_i = nm_next(nic_i, lim);
|
||||
}
|
||||
kring->nr_hwcur = head;
|
||||
|
||||
wmb(); /* synchronize writes to the NIC ring */
|
||||
|
||||
txr->next_to_use = nic_i;
|
||||
NM_WR_TX_TAIL(nic_i);
|
||||
mmiowb(); // XXX where do we need this ?
|
||||
}
|
||||
|
||||
/*
|
||||
* Second part: reclaim buffers for completed transmissions.
|
||||
*/
|
||||
if (flags & NAF_FORCE_RECLAIM || nm_kr_txempty(kring)) {
|
||||
/* record completed transmissions using TDH */
|
||||
nic_i = NM_RD_TX_HEAD(); // XXX could scan descriptors ?
|
||||
if (nic_i >= kring->nkr_num_slots) { /* XXX can it happen ? */
|
||||
D("TDH wrap %d", nic_i);
|
||||
nic_i -= kring->nkr_num_slots;
|
||||
}
|
||||
txr->next_to_clean = nic_i;
|
||||
kring->nr_hwtail = nm_prev(netmap_idx_n2k(kring, nic_i), lim);
|
||||
}
|
||||
out:
|
||||
nm_txsync_finalize(kring);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Reconcile kernel and user view of the receive ring.
|
||||
*/
|
||||
static int
|
||||
e1000_netmap_rxsync(struct netmap_kring *kring, int flags)
|
||||
{
|
||||
struct netmap_adapter *na = kring->na;
|
||||
struct ifnet *ifp = na->ifp;
|
||||
struct netmap_ring *ring = kring->ring;
|
||||
u_int ring_nr = kring->ring_id;
|
||||
u_int nm_i; /* index into the netmap ring */
|
||||
u_int nic_i; /* index into the NIC ring */
|
||||
u_int n;
|
||||
u_int const lim = kring->nkr_num_slots - 1;
|
||||
u_int const head = nm_rxsync_prologue(kring);
|
||||
int force_update = (flags & NAF_FORCE_READ) || kring->nr_kflags & NKR_PENDINTR;
|
||||
|
||||
/* device-specific */
|
||||
struct SOFTC_T *adapter = netdev_priv(ifp);
|
||||
struct e1000_ring *rxr = &adapter->rx_ring[ring_nr];
|
||||
|
||||
if (!netif_carrier_ok(ifp))
|
||||
return 0;
|
||||
|
||||
if (head > lim)
|
||||
return netmap_ring_reinit(kring);
|
||||
|
||||
rmb();
|
||||
|
||||
/*
|
||||
* First part: import newly received packets.
|
||||
*/
|
||||
if (netmap_no_pendintr || force_update) {
|
||||
uint16_t slot_flags = kring->nkr_slot_flags;
|
||||
int strip_crc = (adapter->flags2 & FLAG2_CRC_STRIPPING) ? 0 : 4;
|
||||
|
||||
nic_i = rxr->next_to_clean;
|
||||
nm_i = netmap_idx_n2k(kring, nic_i);
|
||||
|
||||
for (n = 0; ; n++) {
|
||||
NM_E1K_RX_DESC_T *curr = E1000_RX_DESC_EXT(*rxr, nic_i);
|
||||
uint32_t staterr = le32toh(curr->NM_E1R_RX_STATUS);
|
||||
|
||||
if ((staterr & E1000_RXD_STAT_DD) == 0)
|
||||
break;
|
||||
ring->slot[nm_i].len = le16toh(curr->NM_E1R_RX_LENGTH) - strip_crc;
|
||||
ring->slot[nm_i].flags = slot_flags;
|
||||
nm_i = nm_next(nm_i, lim);
|
||||
nic_i = nm_next(nic_i, lim);
|
||||
}
|
||||
if (n) { /* update the state variables */
|
||||
rxr->next_to_clean = nic_i;
|
||||
kring->nr_hwtail = nm_i;
|
||||
}
|
||||
kring->nr_kflags &= ~NKR_PENDINTR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Second part: skip past packets that userspace has released.
|
||||
*/
|
||||
nm_i = kring->nr_hwcur;
|
||||
if (nm_i != head) {
|
||||
nic_i = netmap_idx_k2n(kring, nm_i);
|
||||
for (n = 0; nm_i != head; n++) {
|
||||
struct netmap_slot *slot = &ring->slot[nm_i];
|
||||
uint64_t paddr;
|
||||
void *addr = PNMB(slot, &paddr);
|
||||
NM_E1K_RX_DESC_T *curr = E1000_RX_DESC_EXT(*rxr, nic_i);
|
||||
|
||||
if (addr == netmap_buffer_base) /* bad buf */
|
||||
goto ring_reset;
|
||||
curr->NM_E1R_RX_BUFADDR = htole64(paddr); /* reload ext.desc. addr. */
|
||||
if (slot->flags & NS_BUF_CHANGED) {
|
||||
/* buffer has changed, reload map */
|
||||
// netmap_reload_map(pdev, DMA_TO_DEVICE, old_paddr, addr)
|
||||
slot->flags &= ~NS_BUF_CHANGED;
|
||||
}
|
||||
curr->NM_E1R_RX_STATUS = 0;
|
||||
nm_i = nm_next(nm_i, lim);
|
||||
nic_i = nm_next(nic_i, lim);
|
||||
}
|
||||
kring->nr_hwcur = head;
|
||||
rxr->next_to_use = nic_i; // XXX not really used
|
||||
wmb();
|
||||
/*
|
||||
* IMPORTANT: we must leave one free slot in the ring,
|
||||
* so move nic_i back by one unit
|
||||
*/
|
||||
nic_i = nm_prev(nic_i, lim);
|
||||
NM_WR_RX_TAIL(nic_i);
|
||||
}
|
||||
|
||||
/* tell userspace that there might be new packets */
|
||||
nm_rxsync_finalize(kring);
|
||||
|
||||
return 0;
|
||||
|
||||
ring_reset:
|
||||
return netmap_ring_reinit(kring);
|
||||
}
|
||||
|
||||
|
||||
/* diagnostic routine to catch errors */
|
||||
static void e1000e_no_rx_alloc(struct SOFTC_T *a, int n)
|
||||
{
|
||||
D("e1000->alloc_rx_buf should not be called");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Make the tx and rx rings point to the netmap buffers.
|
||||
*/
|
||||
static int e1000e_netmap_init_buffers(struct SOFTC_T *adapter)
|
||||
{
|
||||
struct ifnet *ifp = adapter->netdev;
|
||||
struct netmap_adapter* na = NA(ifp);
|
||||
struct netmap_slot* slot;
|
||||
struct e1000_ring *rxr = adapter->rx_ring;
|
||||
struct e1000_ring *txr = adapter->tx_ring;
|
||||
int i, si;
|
||||
uint64_t paddr;
|
||||
|
||||
if (!na || !(na->na_flags & NAF_NATIVE_ON)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
slot = netmap_reset(na, NR_RX, 0, 0);
|
||||
if (!slot)
|
||||
return 0; // not in netmap mode XXX check is useless
|
||||
|
||||
adapter->alloc_rx_buf = (void*)e1000e_no_rx_alloc;
|
||||
for (i = 0; i < rxr->count; i++) {
|
||||
// XXX the skb check and cleanup can go away
|
||||
struct e1000_buffer *bi = &rxr->buffer_info[i];
|
||||
si = netmap_idx_n2k(&na->rx_rings[0], i);
|
||||
PNMB(slot + si, &paddr);
|
||||
if (bi->skb)
|
||||
D("rx buf %d was set", i);
|
||||
bi->skb = NULL; // XXX leak if set
|
||||
// netmap_load_map(...)
|
||||
E1000_RX_DESC_EXT(*rxr, i)->NM_E1R_RX_BUFADDR = htole64(paddr);
|
||||
}
|
||||
rxr->next_to_use = 0;
|
||||
/* preserve buffers already made available to clients */
|
||||
i = rxr->count - 1 - nm_kr_rxspace(&na->rx_rings[0]);
|
||||
wmb(); /* Force memory writes to complete */
|
||||
NM_WR_RX_TAIL(i);
|
||||
|
||||
/* now initialize the tx ring */
|
||||
slot = netmap_reset(na, NR_TX, 0, 0);
|
||||
for (i = 0; i < na->num_tx_desc; i++) {
|
||||
si = netmap_idx_n2k(&na->tx_rings[0], i);
|
||||
PNMB(slot + si, &paddr);
|
||||
// netmap_load_map(...)
|
||||
E1000_TX_DESC(*txr, i)->buffer_addr = htole64(paddr);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
e1000_netmap_attach(struct SOFTC_T *adapter)
|
||||
{
|
||||
struct netmap_adapter na;
|
||||
|
||||
bzero(&na, sizeof(na));
|
||||
|
||||
na.ifp = adapter->netdev;
|
||||
na.num_tx_desc = adapter->tx_ring->count;
|
||||
na.num_rx_desc = adapter->rx_ring->count;
|
||||
na.nm_register = e1000_netmap_reg;
|
||||
na.nm_txsync = e1000_netmap_txsync;
|
||||
na.nm_rxsync = e1000_netmap_rxsync;
|
||||
na.num_tx_rings = na.num_rx_rings = 1;
|
||||
netmap_attach(&na);
|
||||
}
|
||||
|
||||
/* end of file */
|
400
netmap/LINUX/if_igb_netmap.h
Normal file
400
netmap/LINUX/if_igb_netmap.h
Normal file
@ -0,0 +1,400 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2014 Luigi Rizzo. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id: if_igb_netmap.h 10878 2012-04-12 22:28:48Z luigi $
|
||||
*
|
||||
* netmap support for: igb (linux version)
|
||||
* For details on netmap support please see ixgbe_netmap.h
|
||||
*/
|
||||
|
||||
|
||||
#include <bsd_glue.h>
|
||||
#include <net/netmap.h>
|
||||
#include <netmap/netmap_kern.h>
|
||||
|
||||
#define SOFTC_T igb_adapter
|
||||
|
||||
|
||||
/*
|
||||
* Adapt to different versions of the driver.
|
||||
* E1000_TX_DESC_ADV etc. have dropped the _ADV suffix at some point.
|
||||
* Also the first argument is now a pointer not the object.
|
||||
*/
|
||||
#ifndef E1000_TX_DESC_ADV
|
||||
#define E1000_TX_DESC_ADV(_r, _i) IGB_TX_DESC(&(_r), _i)
|
||||
#define E1000_RX_DESC_ADV(_r, _i) IGB_RX_DESC(&(_r), _i)
|
||||
#define READ_TDH(_txr) ({struct e1000_hw *hw = &adapter->hw;rd32(E1000_TDH((_txr)->reg_idx));} )
|
||||
#else /* up to 3.2, approximately */
|
||||
#define igb_tx_buffer igb_buffer
|
||||
#define tx_buffer_info buffer_info
|
||||
#define igb_rx_buffer igb_buffer
|
||||
#define rx_buffer_info buffer_info
|
||||
#define READ_TDH(_txr) readl((_txr)->head)
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Register/unregister. We are already under netmap lock.
|
||||
* Only called on the first register or the last unregister.
|
||||
*/
|
||||
static int
|
||||
igb_netmap_reg(struct netmap_adapter *na, int onoff)
|
||||
{
|
||||
struct ifnet *ifp = na->ifp;
|
||||
struct SOFTC_T *adapter = netdev_priv(ifp);
|
||||
|
||||
/* protect against other reinit */
|
||||
while (test_and_set_bit(__IGB_RESETTING, &adapter->state))
|
||||
usleep_range(1000, 2000);
|
||||
|
||||
rtnl_lock();
|
||||
if (netif_running(adapter->netdev))
|
||||
igb_down(adapter);
|
||||
|
||||
/* enable or disable flags and callbacks in na and ifp */
|
||||
if (onoff) {
|
||||
nm_set_native_flags(na);
|
||||
} else {
|
||||
nm_clear_native_flags(na);
|
||||
}
|
||||
if (netif_running(adapter->netdev))
|
||||
igb_up(adapter);
|
||||
else
|
||||
igb_reset(adapter); // XXX is it needed ?
|
||||
|
||||
rtnl_unlock();
|
||||
|
||||
clear_bit(__IGB_RESETTING, &adapter->state);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Reconcile kernel and user view of the transmit ring.
|
||||
*/
|
||||
static int
|
||||
igb_netmap_txsync(struct netmap_kring *kring, int flags)
|
||||
{
|
||||
struct netmap_adapter *na = kring->na;
|
||||
struct ifnet *ifp = na->ifp;
|
||||
struct netmap_ring *ring = kring->ring;
|
||||
u_int ring_nr = kring->ring_id;
|
||||
u_int nm_i; /* index into the netmap ring */
|
||||
u_int nic_i; /* index into the NIC ring */
|
||||
u_int n;
|
||||
u_int const lim = kring->nkr_num_slots - 1;
|
||||
u_int const head = kring->rhead;
|
||||
/* generate an interrupt approximately every half ring */
|
||||
u_int report_frequency = kring->nkr_num_slots >> 1;
|
||||
|
||||
/* device-specific */
|
||||
struct SOFTC_T *adapter = netdev_priv(ifp);
|
||||
struct igb_ring* txr = adapter->tx_ring[ring_nr];
|
||||
|
||||
rmb(); // XXX not in ixgbe ?
|
||||
|
||||
/*
|
||||
* First part: process new packets to send.
|
||||
*/
|
||||
if (!netif_carrier_ok(ifp)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
nm_i = kring->nr_hwcur;
|
||||
if (nm_i != head) { /* we have new packets to send */
|
||||
uint32_t olinfo_status=0;
|
||||
|
||||
nic_i = netmap_idx_k2n(kring, nm_i);
|
||||
for (n = 0; nm_i != head; n++) {
|
||||
struct netmap_slot *slot = &ring->slot[nm_i];
|
||||
u_int len = slot->len;
|
||||
uint64_t paddr;
|
||||
void *addr = PNMB(slot, &paddr);
|
||||
|
||||
/* device-specific */
|
||||
union e1000_adv_tx_desc *curr =
|
||||
E1000_TX_DESC_ADV(*txr, nic_i);
|
||||
int flags = (slot->flags & NS_REPORT ||
|
||||
nic_i == 0 || nic_i == report_frequency) ?
|
||||
E1000_TXD_CMD_RS : 0;
|
||||
|
||||
NM_CHECK_ADDR_LEN(addr, len);
|
||||
|
||||
if (slot->flags & NS_BUF_CHANGED) {
|
||||
/* buffer has changed, reload map */
|
||||
// netmap_reload_map(pdev, DMA_TO_DEVICE, old_paddr, addr);
|
||||
}
|
||||
slot->flags &= ~(NS_REPORT | NS_BUF_CHANGED);
|
||||
|
||||
/* Fill the slot in the NIC ring. */
|
||||
curr->read.buffer_addr = htole64(paddr);
|
||||
// XXX check olinfo and cmd_type_len
|
||||
curr->read.olinfo_status =
|
||||
htole32(olinfo_status |
|
||||
(len<< E1000_ADVTXD_PAYLEN_SHIFT));
|
||||
curr->read.cmd_type_len = htole32(len | flags |
|
||||
E1000_ADVTXD_DTYP_DATA | E1000_ADVTXD_DCMD_DEXT |
|
||||
E1000_ADVTXD_DCMD_IFCS | E1000_TXD_CMD_EOP);
|
||||
nm_i = nm_next(nm_i, lim);
|
||||
nic_i = nm_next(nic_i, lim);
|
||||
}
|
||||
kring->nr_hwcur = head;
|
||||
|
||||
wmb(); /* synchronize writes to the NIC ring */
|
||||
|
||||
txr->next_to_use = nic_i; /* XXX what for ? */
|
||||
/* (re)start the tx unit up to slot nic_i (excluded) */
|
||||
writel(nic_i, txr->tail);
|
||||
mmiowb(); // XXX where do we need this ?
|
||||
}
|
||||
|
||||
/*
|
||||
* Second part: reclaim buffers for completed transmissions.
|
||||
*/
|
||||
if (flags & NAF_FORCE_RECLAIM || nm_kr_txempty(kring)) {
|
||||
/* record completed transmissions using TDH */
|
||||
nic_i = READ_TDH(txr);
|
||||
if (nic_i >= kring->nkr_num_slots) { /* XXX can it happen ? */
|
||||
D("TDH wrap %d", nic_i);
|
||||
nic_i -= kring->nkr_num_slots;
|
||||
}
|
||||
txr->next_to_use = nic_i;
|
||||
kring->nr_hwtail = nm_prev(netmap_idx_n2k(kring, nic_i), lim);
|
||||
}
|
||||
out:
|
||||
nm_txsync_finalize(kring);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Reconcile kernel and user view of the receive ring.
|
||||
*/
|
||||
static int
|
||||
igb_netmap_rxsync(struct netmap_kring *kring, int flags)
|
||||
{
|
||||
struct netmap_adapter *na = kring->na;
|
||||
struct ifnet *ifp = na->ifp;
|
||||
struct netmap_ring *ring = kring->ring;
|
||||
u_int ring_nr = kring->ring_id;
|
||||
u_int nm_i; /* index into the netmap ring */
|
||||
u_int nic_i; /* index into the NIC ring */
|
||||
u_int n;
|
||||
u_int const lim = kring->nkr_num_slots - 1;
|
||||
u_int const head = nm_rxsync_prologue(kring);
|
||||
int force_update = (flags & NAF_FORCE_READ) || kring->nr_kflags & NKR_PENDINTR;
|
||||
|
||||
/* device-specific */
|
||||
struct SOFTC_T *adapter = netdev_priv(ifp);
|
||||
struct igb_ring *rxr = adapter->rx_ring[ring_nr];
|
||||
|
||||
if (!netif_carrier_ok(ifp))
|
||||
return 0;
|
||||
|
||||
if (head > lim)
|
||||
return netmap_ring_reinit(kring);
|
||||
|
||||
rmb();
|
||||
|
||||
/*
|
||||
* First part: import newly received packets.
|
||||
*/
|
||||
if (netmap_no_pendintr || force_update) {
|
||||
uint16_t slot_flags = kring->nkr_slot_flags;
|
||||
|
||||
nic_i = rxr->next_to_clean;
|
||||
nm_i = netmap_idx_n2k(kring, nic_i);
|
||||
|
||||
for (n = 0; ; n++) {
|
||||
union e1000_adv_rx_desc *curr =
|
||||
E1000_RX_DESC_ADV(*rxr, nic_i);
|
||||
uint32_t staterr = le32toh(curr->wb.upper.status_error);
|
||||
|
||||
if ((staterr & E1000_RXD_STAT_DD) == 0)
|
||||
break;
|
||||
ring->slot[nm_i].len = le16toh(curr->wb.upper.length);
|
||||
ring->slot[nm_i].flags = slot_flags;
|
||||
nm_i = nm_next(nm_i, lim);
|
||||
nic_i = nm_next(nic_i, lim);
|
||||
}
|
||||
if (n) { /* update the state variables */
|
||||
rxr->next_to_clean = nic_i;
|
||||
kring->nr_hwtail = nm_i;
|
||||
}
|
||||
kring->nr_kflags &= ~NKR_PENDINTR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Second part: skip past packets that userspace has released.
|
||||
*/
|
||||
nm_i = kring->nr_hwcur;
|
||||
if (nm_i != head) {
|
||||
nic_i = netmap_idx_k2n(kring, nm_i);
|
||||
for (n = 0; nm_i != head; n++) {
|
||||
struct netmap_slot *slot = &ring->slot[nm_i];
|
||||
uint64_t paddr;
|
||||
void *addr = PNMB(slot, &paddr);
|
||||
union e1000_adv_rx_desc *curr = E1000_RX_DESC_ADV(*rxr, nic_i);
|
||||
|
||||
if (addr == netmap_buffer_base) /* bad buf */
|
||||
goto ring_reset;
|
||||
|
||||
if (slot->flags & NS_BUF_CHANGED) {
|
||||
// netmap_reload_map(pdev, DMA_FROM_DEVICE, old_paddr, addr);
|
||||
slot->flags &= ~NS_BUF_CHANGED;
|
||||
}
|
||||
curr->read.pkt_addr = htole64(paddr);
|
||||
curr->read.hdr_addr = 0;
|
||||
nm_i = nm_next(nm_i, lim);
|
||||
nic_i = nm_next(nic_i, lim);
|
||||
}
|
||||
kring->nr_hwcur = head;
|
||||
wmb();
|
||||
rxr->next_to_use = nic_i; // XXX not really used
|
||||
/*
|
||||
* IMPORTANT: we must leave one free slot in the ring,
|
||||
* so move nic_i back by one unit
|
||||
*/
|
||||
nic_i = nm_prev(nic_i, lim);
|
||||
writel(nic_i, rxr->tail);
|
||||
}
|
||||
|
||||
/* tell userspace that there might be new packets */
|
||||
nm_rxsync_finalize(kring);
|
||||
|
||||
return 0;
|
||||
|
||||
ring_reset:
|
||||
return netmap_ring_reinit(kring);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
igb_netmap_configure_tx_ring(struct SOFTC_T *adapter, int ring_nr)
|
||||
{
|
||||
struct ifnet *ifp = adapter->netdev;
|
||||
struct netmap_adapter* na = NA(ifp);
|
||||
struct netmap_slot* slot;
|
||||
struct igb_ring *txr = adapter->tx_ring[ring_nr];
|
||||
int i, si;
|
||||
void *addr;
|
||||
uint64_t paddr;
|
||||
|
||||
if (!na || !(na->na_flags & NAF_NATIVE_ON)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
slot = netmap_reset(na, NR_TX, ring_nr, 0);
|
||||
if (!slot)
|
||||
return 0; // XXX this should never happen
|
||||
for (i = 0; i < na->num_tx_desc; i++) {
|
||||
union e1000_adv_tx_desc *tx_desc;
|
||||
si = netmap_idx_n2k(&na->tx_rings[ring_nr], i);
|
||||
addr = PNMB(slot + si, &paddr);
|
||||
tx_desc = E1000_TX_DESC_ADV(*txr, i);
|
||||
tx_desc->read.buffer_addr = htole64(paddr);
|
||||
/* actually we don't care to init the rings here */
|
||||
}
|
||||
return 1; // success
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
igb_netmap_configure_rx_ring(struct igb_ring *rxr)
|
||||
{
|
||||
struct ifnet *ifp = rxr->netdev;
|
||||
struct netmap_adapter* na = NA(ifp);
|
||||
int reg_idx = rxr->reg_idx;
|
||||
struct netmap_slot* slot;
|
||||
u_int i;
|
||||
|
||||
if (!na || !(na->na_flags & NAF_NATIVE_ON)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX watch out, the main driver must not use
|
||||
* split headers. The buffer len should be written
|
||||
* into wr32(E1000_SRRCTL(reg_idx), srrctl) with options
|
||||
* something like
|
||||
* srrctl = ALIGN(buffer_len, 1024) >>
|
||||
* E1000_SRRCTL_BSIZEPKT_SHIFT;
|
||||
* srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF;
|
||||
* srrctl |= E1000_SRRCTL_DROP_EN;
|
||||
*/
|
||||
slot = netmap_reset(na, NR_RX, reg_idx, 0);
|
||||
if (!slot)
|
||||
return 0; // not in netmap mode
|
||||
|
||||
for (i = 0; i < rxr->count; i++) {
|
||||
union e1000_adv_rx_desc *rx_desc;
|
||||
uint64_t paddr;
|
||||
int si = netmap_idx_n2k(&na->rx_rings[reg_idx], i);
|
||||
|
||||
#if 0
|
||||
// XXX the skb check can go away
|
||||
struct igb_rx_buffer *bi = &rxr->rx_buffer_info[i];
|
||||
if (bi->skb)
|
||||
D("rx buf %d was set", i);
|
||||
bi->skb = NULL; // XXX leak if set
|
||||
#endif /* useless */
|
||||
|
||||
PNMB(slot + si, &paddr);
|
||||
rx_desc = E1000_RX_DESC_ADV(*rxr, i);
|
||||
rx_desc->read.hdr_addr = 0;
|
||||
rx_desc->read.pkt_addr = htole64(paddr);
|
||||
}
|
||||
rxr->next_to_use = 0;
|
||||
/* preserve buffers already made available to clients */
|
||||
i = rxr->count - 1 - nm_kr_rxspace(&na->rx_rings[reg_idx]);
|
||||
|
||||
wmb(); /* Force memory writes to complete */
|
||||
ND("%s rxr%d.tail %d", ifp->if_xname, reg_idx, i);
|
||||
writel(i, rxr->tail);
|
||||
return 1; // success
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
igb_netmap_attach(struct SOFTC_T *adapter)
|
||||
{
|
||||
struct netmap_adapter na;
|
||||
|
||||
bzero(&na, sizeof(na));
|
||||
|
||||
na.ifp = adapter->netdev;
|
||||
na.num_tx_desc = adapter->tx_ring_count;
|
||||
na.num_rx_desc = adapter->rx_ring_count;
|
||||
na.nm_register = igb_netmap_reg;
|
||||
na.nm_txsync = igb_netmap_txsync;
|
||||
na.nm_rxsync = igb_netmap_rxsync;
|
||||
na.num_tx_rings = adapter->num_tx_queues;
|
||||
na.num_rx_rings = adapter->num_rx_queues;
|
||||
netmap_attach(&na);
|
||||
}
|
||||
|
||||
/* end of file */
|
350
netmap/LINUX/if_re_netmap_linux.h
Normal file
350
netmap/LINUX/if_re_netmap_linux.h
Normal file
@ -0,0 +1,350 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2014 Luigi Rizzo. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* $Id: if_re_netmap_linux.h 10679 2012-02-28 13:42:18Z luigi $
|
||||
*
|
||||
* netmap support for: r8169 (re, linux version)
|
||||
* For details on netmap support please see ixgbe_netmap.h
|
||||
* 1 tx ring, 1 rx ring, 1 lock, crcstrip ? reinit tx addr,
|
||||
*/
|
||||
|
||||
|
||||
#include <bsd_glue.h>
|
||||
#include <net/netmap.h>
|
||||
#include <netmap/netmap_kern.h>
|
||||
|
||||
|
||||
static void rtl8169_wait_for_quiescence(struct ifnet *);
|
||||
#define SOFTC_T rtl8169_private
|
||||
|
||||
|
||||
/*
|
||||
* Register/unregister, mostly the reinit task
|
||||
*/
|
||||
static int
|
||||
re_netmap_reg(struct netmap_adapter *na, int onoff)
|
||||
{
|
||||
struct ifnet *ifp = na->ifp;
|
||||
int error = 0;
|
||||
|
||||
rtnl_lock();
|
||||
rtl8169_wait_for_quiescence(ifp);
|
||||
rtl8169_close(ifp);
|
||||
|
||||
/* enable or disable flags and callbacks in na and ifp */
|
||||
if (onoff) {
|
||||
nm_set_native_flags(na);
|
||||
|
||||
if (rtl8169_open(ifp) < 0) {
|
||||
error = ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
fail:
|
||||
nm_clear_native_flags(na);
|
||||
error = rtl8169_open(ifp) ? EINVAL : 0;
|
||||
}
|
||||
rtnl_unlock();
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Reconcile kernel and user view of the transmit ring.
|
||||
*/
|
||||
static int
|
||||
re_netmap_txsync(struct netmap_kring *kring, int flags)
|
||||
{
|
||||
struct netmap_adapter *na = kring->na;
|
||||
struct ifnet *ifp = na->ifp;
|
||||
struct netmap_ring *ring = kring->ring;
|
||||
u_int nm_i; /* index into the netmap ring */
|
||||
u_int nic_i; /* index into the NIC ring */
|
||||
u_int n;
|
||||
u_int const lim = kring->nkr_num_slots - 1;
|
||||
u_int const head = kring->rhead;
|
||||
|
||||
/* device-specific */
|
||||
struct SOFTC_T *sc = netdev_priv(ifp);
|
||||
void __iomem *ioaddr = sc->mmio_addr;
|
||||
|
||||
rmb();
|
||||
|
||||
/*
|
||||
* First part: process new packets to send.
|
||||
*/
|
||||
if (!netif_carrier_ok(ifp)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
nm_i = kring->nr_hwcur;
|
||||
if (nm_i != head) { /* we have new packets to send */
|
||||
nic_i = sc->cur_tx; // XXX use internal macro ?
|
||||
for (n = 0; nm_i != head; n++) {
|
||||
struct netmap_slot *slot = &ring->slot[nm_i];
|
||||
int len = slot->len;
|
||||
uint64_t paddr;
|
||||
void *addr = PNMB(slot, &paddr);
|
||||
|
||||
/* device-specific */
|
||||
struct TxDesc *curr = &sc->TxDescArray[nic_i];
|
||||
uint32_t flags = slot->len | LastFrag | DescOwn | FirstFrag ;
|
||||
|
||||
NM_CHECK_ADDR_LEN(addr, len);
|
||||
|
||||
if (nic_i == lim) /* mark end of ring */
|
||||
flags |= RingEnd;
|
||||
|
||||
if (slot->flags & NS_BUF_CHANGED) {
|
||||
/* buffer has changed, reload map */
|
||||
// netmap_reload_map(pdev, DMA_TO_DEVICE, old_paddr, addr);
|
||||
curr->addr = htole64(paddr);
|
||||
}
|
||||
slot->flags &= ~(NS_REPORT | NS_BUF_CHANGED);
|
||||
curr->opts1 = htole32(flags);
|
||||
nm_i = nm_next(nm_i, lim);
|
||||
nic_i = nm_next(nic_i, lim);
|
||||
}
|
||||
kring->nr_hwcur = head;
|
||||
|
||||
sc->cur_tx = nic_i;
|
||||
wmb(); /* synchronize writes to the NIC ring */
|
||||
RTL_W8(TxPoll, NPQ); /* start ? */
|
||||
}
|
||||
|
||||
/*
|
||||
* Second part: reclaim buffers for completed transmissions.
|
||||
*/
|
||||
if (flags & NAF_FORCE_RECLAIM || nm_kr_txempty(kring)) {
|
||||
for (n = 0, nic_i = sc->dirty_tx; nic_i != sc->cur_tx; n++) {
|
||||
if (le32toh(sc->TxDescArray[nic_i].opts1) & DescOwn)
|
||||
break;
|
||||
if (++nic_i == NUM_TX_DESC)
|
||||
nic_i = 0;
|
||||
}
|
||||
if (n > 0) {
|
||||
sc->dirty_tx = nic_i;
|
||||
kring->nr_hwtail = nm_prev(netmap_idx_n2k(kring, nic_i), lim);
|
||||
}
|
||||
}
|
||||
out:
|
||||
nm_txsync_finalize(kring);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Reconcile kernel and user view of the receive ring.
|
||||
*/
|
||||
static int
|
||||
re_netmap_rxsync(struct netmap_kring *kring, int flags)
|
||||
{
|
||||
struct netmap_adapter *na = kring->na;
|
||||
struct ifnet *ifp = na->ifp;
|
||||
struct SOFTC_T *sc = netdev_priv(ifp);
|
||||
struct netmap_ring *ring = kring->ring;
|
||||
u_int nm_i; /* index into the netmap ring */
|
||||
u_int nic_i; /* index into the NIC ring */
|
||||
u_int n;
|
||||
u_int const lim = kring->nkr_num_slots - 1;
|
||||
u_int const head = nm_rxsync_prologue(kring);
|
||||
int force_update = (flags & NAF_FORCE_READ) || kring->nr_kflags & NKR_PENDINTR;
|
||||
|
||||
if (!netif_carrier_ok(ifp))
|
||||
return 0;
|
||||
|
||||
if (head > lim)
|
||||
return netmap_ring_reinit(kring);
|
||||
|
||||
rmb();
|
||||
/*
|
||||
* First part: import newly received packets.
|
||||
*
|
||||
* NOTE: This device uses all the buffers in the ring, so we
|
||||
* need another termination condition in addition to DescOwn
|
||||
* cleared (all buffers could have it cleared. The easiest one
|
||||
* is to stop right before nm_hwcur.
|
||||
*/
|
||||
if (netmap_no_pendintr || force_update) {
|
||||
uint16_t slot_flags = kring->nkr_slot_flags;
|
||||
uint32_t stop_i = nm_prev(kring->nr_hwcur, lim);
|
||||
|
||||
nic_i = sc->cur_rx; /* next pkt to check */
|
||||
nm_i = netmap_idx_n2k(kring, nic_i);
|
||||
|
||||
while (nm_i != stop_i) {
|
||||
struct RxDesc *cur_rx = &sc->RxDescArray[nic_i];
|
||||
uint32_t rxstat = le32toh(cur_rx->opts1);
|
||||
uint32_t total_len;
|
||||
|
||||
if ((rxstat & DescOwn) != 0)
|
||||
break;
|
||||
total_len = rxstat & 0x00001FFF;
|
||||
/* XXX subtract crc */
|
||||
total_len = (total_len < 4) ? 0 : total_len - 4;
|
||||
ring->slot[nm_i].len = total_len;
|
||||
ring->slot[nm_i].flags = slot_flags;
|
||||
// ifp->stats.rx_packets++;
|
||||
nm_i = nm_next(nm_i, lim);
|
||||
nic_i = nm_next(nic_i, lim);
|
||||
}
|
||||
sc->cur_rx = nic_i;
|
||||
kring->nr_hwtail = nm_i;
|
||||
kring->nr_kflags &= ~NKR_PENDINTR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Second part: skip past packets that userspace has released.
|
||||
*/
|
||||
nm_i = kring->nr_hwcur;
|
||||
if (nm_i != head) {
|
||||
nic_i = netmap_idx_k2n(kring, nm_i);
|
||||
for (n = 0; nm_i != head; n++) {
|
||||
struct netmap_slot *slot = &ring->slot[nm_i];
|
||||
uint64_t paddr;
|
||||
void *addr = PNMB(slot, &paddr);
|
||||
|
||||
struct RxDesc *curr = &sc->RxDescArray[nic_i];
|
||||
uint32_t flags = NETMAP_BUF_SIZE | DescOwn;
|
||||
|
||||
if (addr == netmap_buffer_base) /* bad buf */
|
||||
goto ring_reset;
|
||||
|
||||
if (nic_i == lim) /* mark end of ring */
|
||||
flags |= RingEnd;
|
||||
|
||||
if (slot->flags & NS_BUF_CHANGED) {
|
||||
/* buffer has changed, reload map */
|
||||
// netmap_reload_map(pdev, DMA_TO_DEVICE, old_paddr, addr);
|
||||
curr->addr = htole64(paddr);
|
||||
slot->flags &= ~NS_BUF_CHANGED;
|
||||
}
|
||||
curr->opts1 = htole32(flags);
|
||||
nm_i = nm_next(nm_i, lim);
|
||||
nic_i = nm_next(nic_i, lim);
|
||||
}
|
||||
kring->nr_hwcur = head;
|
||||
wmb(); // XXX needed ?
|
||||
}
|
||||
|
||||
/* tell userspace that there might be new packets */
|
||||
nm_rxsync_finalize(kring);
|
||||
return 0;
|
||||
|
||||
ring_reset:
|
||||
return netmap_ring_reinit(kring);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Additional routines to init the tx and rx rings.
|
||||
* In other drivers we do that inline in the main code.
|
||||
*/
|
||||
static int
|
||||
re_netmap_tx_init(struct SOFTC_T *sc)
|
||||
{
|
||||
struct netmap_adapter *na = NA(sc->dev);
|
||||
struct netmap_slot *slot;
|
||||
struct TxDesc *desc = sc->TxDescArray;
|
||||
int i, l;
|
||||
uint64_t paddr;
|
||||
|
||||
if (!na || !(na->na_flags & NAF_NATIVE_ON)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
slot = netmap_reset(na, NR_TX, 0, 0);
|
||||
/* slot is NULL if we are not in netmap mode XXX cannot happen */
|
||||
if (!slot)
|
||||
return 0;
|
||||
|
||||
/* l points in the netmap ring, i points in the NIC ring */
|
||||
for (i = 0; i < na->num_tx_desc; i++) {
|
||||
l = netmap_idx_n2k(&na->tx_rings[0], i);
|
||||
PNMB(slot + l, &paddr);
|
||||
desc[i].addr = htole64(paddr);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
re_netmap_rx_init(struct SOFTC_T *sc)
|
||||
{
|
||||
struct netmap_adapter *na = NA(sc->dev);
|
||||
struct netmap_slot *slot;
|
||||
struct RxDesc *desc = sc->RxDescArray;
|
||||
uint32_t cmdstat;
|
||||
int i, lim, l;
|
||||
uint64_t paddr;
|
||||
|
||||
if (!na || !(na->na_flags & NAF_NATIVE_ON)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
slot = netmap_reset(na, NR_RX, 0, 0);
|
||||
if (!slot)
|
||||
return 0; /* XXX cannot happen */
|
||||
/*
|
||||
* Do not release the slots owned by userspace
|
||||
* XXX we use all slots, so no '-1' here
|
||||
* XXX do we need -1 instead ?
|
||||
*/
|
||||
lim = na->num_rx_desc /* - 1 */ - nm_kr_rxspace(&na->rx_rings[0]);
|
||||
for (i = 0; i < na->num_rx_desc; i++) {
|
||||
l = netmap_idx_n2k(&na->rx_rings[0], i);
|
||||
PNMB(slot + l, &paddr);
|
||||
cmdstat = NETMAP_BUF_SIZE;
|
||||
if (i == na->num_rx_desc - 1)
|
||||
cmdstat |= RingEnd;
|
||||
if (i < lim)
|
||||
cmdstat |= DescOwn;
|
||||
desc[i].opts1 = htole32(cmdstat);
|
||||
desc[i].addr = htole64(paddr);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
re_netmap_attach(struct SOFTC_T *sc)
|
||||
{
|
||||
struct netmap_adapter na;
|
||||
|
||||
bzero(&na, sizeof(na));
|
||||
|
||||
na.ifp = sc->dev;
|
||||
na.num_tx_desc = NUM_TX_DESC;
|
||||
na.num_rx_desc = NUM_RX_DESC;
|
||||
na.nm_txsync = re_netmap_txsync;
|
||||
na.nm_rxsync = re_netmap_rxsync;
|
||||
na.nm_register = re_netmap_reg;
|
||||
na.num_tx_rings = na.num_rx_rings = 1;
|
||||
netmap_attach(&na);
|
||||
}
|
||||
|
||||
/* end of file */
|
503
netmap/LINUX/ixgbe_netmap_linux.h
Normal file
503
netmap/LINUX/ixgbe_netmap_linux.h
Normal file
@ -0,0 +1,503 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2014 Matteo Landi, Luigi Rizzo. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $FreeBSD: head/sys/dev/netmap/ixgbe_netmap.h 230572 2012-01-26 09:55:16Z luigi $
|
||||
*
|
||||
* netmap support for: ixgbe (LINUX version)
|
||||
*
|
||||
* This file is meant to be a reference on how to implement
|
||||
* netmap support for a network driver.
|
||||
* This file contains code but only static or inline functions used
|
||||
* by a single driver. To avoid replication of code we just #include
|
||||
* it near the beginning of the standard driver.
|
||||
*/
|
||||
|
||||
|
||||
#include <bsd_glue.h>
|
||||
#include <net/netmap.h>
|
||||
#include <netmap/netmap_kern.h>
|
||||
|
||||
#define SOFTC_T ixgbe_adapter
|
||||
|
||||
/*
|
||||
* Adaptation to different versions of the driver.
|
||||
* Recent drivers (3.4 and above) redefine some macros
|
||||
*/
|
||||
#ifndef IXGBE_TX_DESC_ADV
|
||||
#define IXGBE_TX_DESC_ADV IXGBE_TX_DESC
|
||||
#define IXGBE_RX_DESC_ADV IXGBE_RX_DESC
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Register/unregister. We are already under netmap lock.
|
||||
* Only called on the first register or the last unregister.
|
||||
*/
|
||||
static int
|
||||
ixgbe_netmap_reg(struct netmap_adapter *na, int onoff)
|
||||
{
|
||||
struct ifnet *ifp = na->ifp;
|
||||
struct SOFTC_T *adapter = netdev_priv(ifp);
|
||||
|
||||
// adapter->netdev->trans_start = jiffies; // disable watchdog ?
|
||||
/* protect against other reinit */
|
||||
while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state))
|
||||
usleep_range(1000, 2000);
|
||||
|
||||
rtnl_lock();
|
||||
if (netif_running(adapter->netdev))
|
||||
ixgbe_down(adapter);
|
||||
|
||||
/* enable or disable flags and callbacks in na and ifp */
|
||||
if (onoff) {
|
||||
nm_set_native_flags(na);
|
||||
} else {
|
||||
nm_clear_native_flags(na);
|
||||
}
|
||||
/* XXX SRIOV migth need another 2sec wait */
|
||||
if (netif_running(adapter->netdev))
|
||||
ixgbe_up(adapter); /* also enables intr */
|
||||
rtnl_unlock();
|
||||
|
||||
clear_bit(__IXGBE_RESETTING, &adapter->state);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Reconcile kernel and user view of the transmit ring.
|
||||
*
|
||||
* Userspace wants to send packets up to the one before ring->head,
|
||||
* kernel knows kring->nr_hwcur is the first unsent packet.
|
||||
*
|
||||
* Here we push packets out (as many as possible), and possibly
|
||||
* reclaim buffers from previously completed transmission.
|
||||
*
|
||||
* ring->tail is updated on return.
|
||||
* ring->head is never used here.
|
||||
*
|
||||
* The caller (netmap) guarantees that there is only one instance
|
||||
* running at any time. Any interference with other driver
|
||||
* methods should be handled by the individual drivers.
|
||||
*/
|
||||
static int
|
||||
ixgbe_netmap_txsync(struct netmap_kring *kring, int flags)
|
||||
{
|
||||
struct netmap_adapter *na = kring->na;
|
||||
struct ifnet *ifp = na->ifp;
|
||||
struct netmap_ring *ring = kring->ring;
|
||||
u_int ring_nr = kring->ring_id;
|
||||
u_int nm_i; /* index into the netmap ring */
|
||||
u_int nic_i; /* index into the NIC ring */
|
||||
u_int n;
|
||||
u_int const lim = kring->nkr_num_slots - 1;
|
||||
u_int const head = kring->rhead;
|
||||
/*
|
||||
* interrupts on every tx packet are expensive so request
|
||||
* them every half ring, or where NS_REPORT is set
|
||||
*/
|
||||
u_int report_frequency = kring->nkr_num_slots >> 1;
|
||||
|
||||
/* device-specific */
|
||||
struct SOFTC_T *adapter = netdev_priv(ifp);
|
||||
struct ixgbe_ring *txr = adapter->tx_ring[ring_nr];
|
||||
int reclaim_tx;
|
||||
|
||||
/*
|
||||
* First part: process new packets to send.
|
||||
* nm_i is the current index in the netmap ring,
|
||||
* nic_i is the corresponding index in the NIC ring.
|
||||
* The two numbers differ because upon a *_init() we reset
|
||||
* the NIC ring but leave the netmap ring unchanged.
|
||||
* For the transmit ring, we have
|
||||
*
|
||||
* nm_i = kring->nr_hwcur
|
||||
* nic_i = IXGBE_TDT (not tracked in the driver)
|
||||
* and
|
||||
* nm_i == (nic_i + kring->nkr_hwofs) % ring_size
|
||||
*
|
||||
* In this driver kring->nkr_hwofs >= 0, but for other
|
||||
* drivers it might be negative as well.
|
||||
*/
|
||||
|
||||
/*
|
||||
* If we have packets to send (kring->nr_hwcur != ring->cur)
|
||||
* iterate over the netmap ring, fetch length and update
|
||||
* the corresponding slot in the NIC ring. Some drivers also
|
||||
* need to update the buffer's physical address in the NIC slot
|
||||
* even NS_BUF_CHANGED is not set (PNMB computes the addresses).
|
||||
*
|
||||
* The netmap_reload_map() calls is especially expensive,
|
||||
* even when (as in this case) the tag is 0, so do only
|
||||
* when the buffer has actually changed.
|
||||
*
|
||||
* If possible do not set the report/intr bit on all slots,
|
||||
* but only a few times per ring or when NS_REPORT is set.
|
||||
*
|
||||
* Finally, on 10G and faster drivers, it might be useful
|
||||
* to prefetch the next slot and txr entry.
|
||||
*/
|
||||
|
||||
if (!netif_carrier_ok(ifp)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
nm_i = kring->nr_hwcur;
|
||||
if (nm_i != head) { /* we have new packets to send */
|
||||
nic_i = netmap_idx_k2n(kring, nm_i);
|
||||
for (n = 0; nm_i != head; n++) {
|
||||
struct netmap_slot *slot = &ring->slot[nm_i];
|
||||
u_int len = slot->len;
|
||||
uint64_t paddr;
|
||||
void *addr = PNMB(slot, &paddr);
|
||||
|
||||
/* device-specific */
|
||||
union ixgbe_adv_tx_desc *curr = IXGBE_TX_DESC_ADV(txr, nic_i);
|
||||
int flags = (slot->flags & NS_REPORT ||
|
||||
nic_i == 0 || nic_i == report_frequency) ?
|
||||
IXGBE_TXD_CMD_RS : 0;
|
||||
|
||||
NM_CHECK_ADDR_LEN(addr, len);
|
||||
|
||||
if (slot->flags & NS_BUF_CHANGED) {
|
||||
/* buffer has changed, reload map */
|
||||
// netmap_reload_map(pdev, DMA_TO_DEVICE, old_addr, addr);
|
||||
}
|
||||
slot->flags &= ~(NS_REPORT | NS_BUF_CHANGED);
|
||||
|
||||
/* Fill the slot in the NIC ring. */
|
||||
curr->read.buffer_addr = htole64(paddr);
|
||||
curr->read.olinfo_status = htole32(len << IXGBE_ADVTXD_PAYLEN_SHIFT);
|
||||
curr->read.cmd_type_len = htole32(len | flags |
|
||||
IXGBE_ADVTXD_DTYP_DATA | IXGBE_ADVTXD_DCMD_DEXT |
|
||||
IXGBE_ADVTXD_DCMD_IFCS | IXGBE_TXD_CMD_EOP);
|
||||
nm_i = nm_next(nm_i, lim);
|
||||
nic_i = nm_next(nic_i, lim);
|
||||
}
|
||||
kring->nr_hwcur = head;
|
||||
|
||||
wmb(); /* synchronize writes to the NIC ring */
|
||||
/* (re)start the tx unit up to slot nic_i (excluded) */
|
||||
IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDT(txr->reg_idx), nic_i);
|
||||
}
|
||||
|
||||
/*
|
||||
* Second part: reclaim buffers for completed transmissions.
|
||||
* Because this is expensive (we read a NIC register etc.)
|
||||
* we only do it in specific cases (see below).
|
||||
*/
|
||||
if (flags & NAF_FORCE_RECLAIM) {
|
||||
reclaim_tx = 1; /* forced reclaim */
|
||||
} else if (!nm_kr_txempty(kring)) {
|
||||
reclaim_tx = 0; /* have buffers, no reclaim */
|
||||
} else {
|
||||
/*
|
||||
* No buffers available. Locate previous slot with
|
||||
* REPORT_STATUS set.
|
||||
* If the slot has DD set, we can reclaim space,
|
||||
* otherwise wait for the next interrupt.
|
||||
* This enables interrupt moderation on the tx
|
||||
* side though it might reduce throughput.
|
||||
*/
|
||||
union ixgbe_adv_tx_desc *txd = IXGBE_TX_DESC_ADV(txr, 0);
|
||||
|
||||
nic_i = txr->next_to_clean + report_frequency;
|
||||
if (nic_i > lim)
|
||||
nic_i -= lim + 1;
|
||||
// round to the closest with dd set
|
||||
nic_i = (nic_i < kring->nkr_num_slots / 4 ||
|
||||
nic_i >= kring->nkr_num_slots*3/4) ?
|
||||
0 : report_frequency;
|
||||
reclaim_tx = txd[nic_i].wb.status & IXGBE_TXD_STAT_DD; // XXX cpu_to_le32 ?
|
||||
}
|
||||
if (reclaim_tx) {
|
||||
/*
|
||||
* Record completed transmissions.
|
||||
* We (re)use the driver's txr->next_to_clean to keep
|
||||
* track of the most recently completed transmission.
|
||||
*
|
||||
* The datasheet discourages the use of TDH to find
|
||||
* out the number of sent packets, but we only set
|
||||
* REPORT STATUS in a few slots so TDH is the only
|
||||
* good way.
|
||||
*/
|
||||
nic_i = IXGBE_READ_REG(&adapter->hw, IXGBE_TDH(ring_nr));
|
||||
if (nic_i >= kring->nkr_num_slots) { /* XXX can it happen ? */
|
||||
D("TDH wrap %d", nic_i);
|
||||
nic_i -= kring->nkr_num_slots;
|
||||
}
|
||||
txr->next_to_clean = nic_i;
|
||||
kring->nr_hwtail = nm_prev(netmap_idx_n2k(kring, nic_i), lim);
|
||||
}
|
||||
out:
|
||||
nm_txsync_finalize(kring);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Reconcile kernel and user view of the receive ring.
|
||||
* Same as for the txsync, this routine must be efficient.
|
||||
* The caller guarantees a single invocations, but races against
|
||||
* the rest of the driver should be handled here.
|
||||
*
|
||||
* When called, userspace has released buffers up to ring->head
|
||||
* (last one excluded).
|
||||
*
|
||||
* If (flags & NAF_FORCE_READ) also check for incoming packets irrespective
|
||||
* of whether or not we received an interrupt.
|
||||
*/
|
||||
static int
|
||||
ixgbe_netmap_rxsync(struct netmap_kring *kring, int flags)
|
||||
{
|
||||
struct netmap_adapter *na = kring->na;
|
||||
struct ifnet *ifp = na->ifp;
|
||||
struct netmap_ring *ring = kring->ring;
|
||||
u_int ring_nr = kring->ring_id;
|
||||
u_int nm_i; /* index into the netmap ring */
|
||||
u_int nic_i; /* index into the NIC ring */
|
||||
u_int n;
|
||||
u_int const lim = kring->nkr_num_slots - 1;
|
||||
u_int const head = nm_rxsync_prologue(kring);
|
||||
int force_update = (flags & NAF_FORCE_READ) || kring->nr_kflags & NKR_PENDINTR;
|
||||
|
||||
/* device-specific */
|
||||
struct SOFTC_T *adapter = netdev_priv(ifp);
|
||||
struct ixgbe_ring *rxr = adapter->rx_ring[ring_nr];
|
||||
|
||||
if (!netif_carrier_ok(ifp))
|
||||
return 0;
|
||||
|
||||
if (head > lim)
|
||||
return netmap_ring_reinit(kring);
|
||||
|
||||
rmb();
|
||||
|
||||
/*
|
||||
* First part: import newly received packets.
|
||||
*
|
||||
* nm_i is the index of the next free slot in the netmap ring,
|
||||
* nic_i is the index of the next received packet in the NIC ring,
|
||||
* and they may differ in case if_init() has been called while
|
||||
* in netmap mode. For the receive ring we have
|
||||
*
|
||||
* nm_i = (kring->nr_hwtail)
|
||||
* nic_i = rxr->next_to_clean; // really next to check
|
||||
* and
|
||||
* nm_i == (nic_i + kring->nkr_hwofs) % ring_size
|
||||
*
|
||||
* rxr->next_to_clean is set to 0 on a ring reinit
|
||||
*/
|
||||
if (netmap_no_pendintr || force_update) {
|
||||
uint16_t slot_flags = kring->nkr_slot_flags;
|
||||
|
||||
nic_i = rxr->next_to_clean;
|
||||
nm_i = netmap_idx_n2k(kring, nic_i);
|
||||
|
||||
for (n = 0; ; n++) {
|
||||
union ixgbe_adv_rx_desc *curr = IXGBE_RX_DESC_ADV(rxr, nic_i);
|
||||
uint32_t staterr = le32toh(curr->wb.upper.status_error);
|
||||
|
||||
if ((staterr & IXGBE_RXD_STAT_DD) == 0)
|
||||
break;
|
||||
ring->slot[nm_i].len = le16toh(curr->wb.upper.length);
|
||||
ring->slot[nm_i].flags = slot_flags;
|
||||
nm_i = nm_next(nm_i, lim);
|
||||
nic_i = nm_next(nic_i, lim);
|
||||
}
|
||||
if (n) { /* update the state variables */
|
||||
rxr->next_to_clean = nic_i;
|
||||
kring->nr_hwtail = nm_i;
|
||||
}
|
||||
kring->nr_kflags &= ~NKR_PENDINTR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Second part: skip past packets that userspace has released.
|
||||
* (kring->nr_hwcur to ring->head excluded),
|
||||
* and make the buffers available for reception.
|
||||
* As usual nm_i is the index in the netmap ring,
|
||||
* nic_i is the index in the NIC ring, and
|
||||
* nm_i == (nic_i + kring->nkr_hwofs) % ring_size
|
||||
*/
|
||||
nm_i = kring->nr_hwcur;
|
||||
if (nm_i != head) {
|
||||
nic_i = netmap_idx_k2n(kring, nm_i);
|
||||
for (n = 0; nm_i != head; n++) {
|
||||
struct netmap_slot *slot = &ring->slot[nm_i];
|
||||
uint64_t paddr;
|
||||
void *addr = PNMB(slot, &paddr);
|
||||
|
||||
union ixgbe_adv_rx_desc *curr = IXGBE_RX_DESC_ADV(rxr, nic_i);
|
||||
if (addr == netmap_buffer_base) /* bad buf */
|
||||
goto ring_reset;
|
||||
|
||||
if (slot->flags & NS_BUF_CHANGED) {
|
||||
/* buffer has changed, reload map */
|
||||
// netmap_reload_map(pdev, DMA_TO_DEVICE, old_addr, addr);
|
||||
slot->flags &= ~NS_BUF_CHANGED;
|
||||
}
|
||||
curr->wb.upper.status_error = 0;
|
||||
curr->read.pkt_addr = htole64(paddr);
|
||||
nm_i = nm_next(nm_i, lim);
|
||||
nic_i = nm_next(nic_i, lim);
|
||||
}
|
||||
kring->nr_hwcur = head;
|
||||
rxr->next_to_use = nic_i; // XXX not really used
|
||||
wmb();
|
||||
/*
|
||||
* IMPORTANT: we must leave one free slot in the ring,
|
||||
* so move nic_i back by one unit
|
||||
*/
|
||||
nic_i = nm_prev(nic_i, lim);
|
||||
IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDT(rxr->reg_idx), nic_i);
|
||||
}
|
||||
|
||||
/* tell userspace that there might be new packets */
|
||||
nm_rxsync_finalize(kring);
|
||||
|
||||
return 0;
|
||||
|
||||
ring_reset:
|
||||
return netmap_ring_reinit(kring);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* if in netmap mode, attach the netmap buffers to the ring and return true.
|
||||
* Otherwise return false.
|
||||
*/
|
||||
static int
|
||||
ixgbe_netmap_configure_tx_ring(struct SOFTC_T *adapter, int ring_nr)
|
||||
{
|
||||
struct netmap_adapter *na = NA(adapter->netdev);
|
||||
struct netmap_slot *slot;
|
||||
//int j;
|
||||
|
||||
if (!na || !(na->na_flags & NAF_NATIVE_ON)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
slot = netmap_reset(na, NR_TX, ring_nr, 0);
|
||||
if (!slot)
|
||||
return 0; // not in netmap; XXX cannot happen
|
||||
#if 0
|
||||
/*
|
||||
* on a generic card we should set the address in the slot.
|
||||
* But on the ixgbe, the address needs to be rewritten
|
||||
* after a transmission so there is nothing do to except
|
||||
* loading the map.
|
||||
*/
|
||||
for (j = 0; j < na->num_tx_desc; j++) {
|
||||
int sj = netmap_idx_n2k(&na->tx_rings[ring_nr], j);
|
||||
uint64_t paddr;
|
||||
void *addr = PNMB(slot + sj, &paddr);
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
ixgbe_netmap_configure_rx_ring(struct SOFTC_T *adapter, int ring_nr)
|
||||
{
|
||||
/*
|
||||
* In netmap mode, we must preserve the buffers made
|
||||
* available to userspace before the if_init()
|
||||
* (this is true by default on the TX side, because
|
||||
* init makes all buffers available to userspace).
|
||||
*
|
||||
* netmap_reset() and the device-specific routines
|
||||
* (e.g. ixgbe_setup_receive_rings()) map these
|
||||
* buffers at the end of the NIC ring, so here we
|
||||
* must set the RDT (tail) register to make sure
|
||||
* they are not overwritten.
|
||||
*
|
||||
* In this driver the NIC ring starts at RDH = 0,
|
||||
* RDT points to the last slot available for reception (?),
|
||||
* so RDT = num_rx_desc - 1 means the whole ring is available.
|
||||
*/
|
||||
struct netmap_adapter *na = NA(adapter->netdev);
|
||||
struct netmap_slot *slot;
|
||||
int lim, i;
|
||||
struct ixgbe_ring *ring = adapter->rx_ring[ring_nr];
|
||||
|
||||
if (!na || !(na->na_flags & NAF_NATIVE_ON)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
slot = netmap_reset(na, NR_RX, ring_nr, 0);
|
||||
/* same as in ixgbe_setup_transmit_ring() */
|
||||
if (!slot)
|
||||
return 0; // not in netmap; XXX cannot happen
|
||||
|
||||
lim = na->num_rx_desc - 1 - nm_kr_rxspace(&na->rx_rings[ring_nr]);
|
||||
|
||||
for (i = 0; i < na->num_rx_desc; i++) {
|
||||
/*
|
||||
* Fill the map and set the buffer address in the NIC ring,
|
||||
* considering the offset between the netmap and NIC rings
|
||||
* (see comment in ixgbe_setup_transmit_ring() ).
|
||||
*/
|
||||
int si = netmap_idx_n2k(&na->rx_rings[ring_nr], i);
|
||||
uint64_t paddr;
|
||||
PNMB(slot + si, &paddr);
|
||||
// netmap_load_map(rxr->ptag, rxbuf->pmap, addr);
|
||||
/* Update descriptor */
|
||||
IXGBE_RX_DESC_ADV(ring, i)->read.pkt_addr = htole64(paddr);
|
||||
}
|
||||
IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDT(ring_nr), lim);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The attach routine, called near the end of ixgbe_attach(),
|
||||
* fills the parameters for netmap_attach() and calls it.
|
||||
* It cannot fail, in the worst case (such as no memory)
|
||||
* netmap mode will be disabled and the driver will only
|
||||
* operate in standard mode.
|
||||
*/
|
||||
static void
|
||||
ixgbe_netmap_attach(struct SOFTC_T *adapter)
|
||||
{
|
||||
struct netmap_adapter na;
|
||||
|
||||
bzero(&na, sizeof(na));
|
||||
|
||||
na.ifp = adapter->netdev;
|
||||
na.num_tx_desc = adapter->tx_ring[0]->count;
|
||||
na.num_rx_desc = adapter->rx_ring[0]->count;
|
||||
na.nm_txsync = ixgbe_netmap_txsync;
|
||||
na.nm_rxsync = ixgbe_netmap_rxsync;
|
||||
na.nm_register = ixgbe_netmap_reg;
|
||||
na.num_tx_rings = adapter->num_tx_queues;
|
||||
na.num_rx_rings = adapter->num_rx_queues;
|
||||
netmap_attach(&na);
|
||||
}
|
||||
|
||||
/* end of file */
|
736
netmap/LINUX/mlx4_netmap_linux.h
Normal file
736
netmap/LINUX/mlx4_netmap_linux.h
Normal file
@ -0,0 +1,736 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2014 Luigi Rizzo. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id: mlx4_netmap_linux.h $
|
||||
*
|
||||
* netmap support for mlx4 (LINUX version)
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <bsd_glue.h>
|
||||
#include <net/netmap.h>
|
||||
#include <netmap/netmap_kern.h>
|
||||
#define SOFTC_T mlx4_en_priv
|
||||
|
||||
/*
|
||||
* This driver is split in multiple small files.
|
||||
* The main device descriptor has type struct mlx4_en_priv *priv;
|
||||
* and we attach to the device in mlx4_en_init_netdev()
|
||||
* (do port numbers start from 1 ?)
|
||||
*
|
||||
* The reconfig routine is in mlx4_en_start_port() (also here)
|
||||
* which is called on a mlx4_en_restart() (watchdog), open and set-mtu.
|
||||
*
|
||||
* priv->num_frags ??
|
||||
* DS_SIZE ??
|
||||
* apparently each rx desc is followed by frag.descriptors
|
||||
* and the rx desc is rounded up to a power of 2.
|
||||
*
|
||||
* Receive code is in en_rx.c
|
||||
* priv->rx_ring_num number of rx rings
|
||||
* rxr = prov->rx_ring[ring_ind] rx ring descriptor
|
||||
* rxr->size number of slots
|
||||
* rxr->prod producer
|
||||
* probably written into a mmio reg at *rxr->wqres.db.db
|
||||
* trimmed to 16 bits.
|
||||
*
|
||||
* Rx init routine:
|
||||
* mlx4_en_activate_rx_rings()
|
||||
* mlx4_en_init_rx_desc()
|
||||
* Transmit code is in en_tx.c
|
||||
*/
|
||||
|
||||
int mlx4_netmap_rx_config(struct SOFTC_T *priv, int ring_nr);
|
||||
int mlx4_netmap_tx_config(struct SOFTC_T *priv, int ring_nr);
|
||||
|
||||
int mlx4_tx_desc_dump(struct mlx4_en_tx_desc *tx_desc);
|
||||
|
||||
#ifdef NETMAP_MLX4_MAIN
|
||||
static inline void
|
||||
nm_pkt_dump(int i, char *buf, int len)
|
||||
{
|
||||
uint8_t *s __attribute__((unused)) = buf+6, *d __attribute__((unused)) = buf;
|
||||
|
||||
RD(10, "%d len %4d %02x:%02x:%02x:%02x:%02x:%02x -> %02x:%02x:%02x:%02x:%02x:%02x",
|
||||
i,
|
||||
len,
|
||||
s[0], s[1], s[2], s[3], s[4], s[5],
|
||||
d[0], d[1], d[2], d[3], d[4], d[5]);
|
||||
}
|
||||
|
||||
/* show the content of the descriptor. Only the first block is printed
|
||||
* to make sure we do not fail on wraparounds (otherwise we would need
|
||||
* base, index and ring size).
|
||||
*/
|
||||
int
|
||||
mlx4_tx_desc_dump(struct mlx4_en_tx_desc *tx_desc)
|
||||
{
|
||||
struct mlx4_wqe_ctrl_seg *ctrl = &tx_desc->ctrl;
|
||||
uint32_t *p = (uint32_t *)tx_desc;
|
||||
int i, l = ctrl->fence_size;
|
||||
|
||||
RD(5,"------- txdesc %p size 0x%x", tx_desc, ctrl->fence_size);
|
||||
if (l > 4)
|
||||
l = 4;
|
||||
for (i = 0; i < l; i++) {
|
||||
RD(20, "[%2d]: 0x%08x 0x%08x 0x%08x 0x%08x", i,
|
||||
ntohl(p[0]), ntohl(p[1]), ntohl(p[2]), ntohl(p[3]));
|
||||
p += 4;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Register/unregister. We are already under (netmap) core lock.
|
||||
* Only called on the first register or the last unregister.
|
||||
*/
|
||||
static int
|
||||
mlx4_netmap_reg(struct netmap_adapter *na, int onoff)
|
||||
{
|
||||
struct ifnet *ifp = na->ifp;
|
||||
struct SOFTC_T *priv = netdev_priv(ifp);
|
||||
int error = 0, need_load = 0;
|
||||
struct mlx4_en_dev *mdev = priv->mdev;
|
||||
|
||||
/*
|
||||
* On enable, flush pending ops, set flag and reinit rings.
|
||||
* On disable, flush again, and restart the interface.
|
||||
*/
|
||||
D("setting netmap mode for %s to %s", ifp->if_xname, onoff ? "ON" : "OFF");
|
||||
// rtnl_lock(); // ???
|
||||
if (netif_running(ifp)) {
|
||||
D("unloading %s", ifp->if_xname);
|
||||
//double_mutex_state_lock(mdev);
|
||||
mutex_lock(&mdev->state_lock);
|
||||
if (onoff == 0) {
|
||||
int i;
|
||||
/* coming from netmap mode, clean up the ring pointers
|
||||
* so we do not crash in mlx4_en_free_tx_buf()
|
||||
* XXX should STAMP the txdesc value to pretend the hw got there
|
||||
* 0x7fffffff plus the bit set to
|
||||
* !!(ring->cons & ring->size)
|
||||
*/
|
||||
for (i = 0; i < na->num_tx_rings; i++) {
|
||||
struct mlx4_en_tx_ring *txr = &priv->tx_ring[i];
|
||||
ND("txr %d : cons %d prod %d txbb %d", i, txr->cons, txr->prod, txr->last_nr_txbb);
|
||||
txr->cons += txr->last_nr_txbb; // XXX should be 1
|
||||
for (;txr->cons != txr->prod; txr->cons++) {
|
||||
uint16_t j = txr->cons & txr->size_mask;
|
||||
uint32_t new_val, *ptr = (uint32_t *)(txr->buf + j * TXBB_SIZE);
|
||||
new_val = cpu_to_be32(STAMP_VAL | (!!(txr->cons & txr->size) << STAMP_SHIFT));
|
||||
ND(10, "old 0x%08x new 0x%08x", *ptr, new_val);
|
||||
*ptr = new_val;
|
||||
}
|
||||
}
|
||||
}
|
||||
mlx4_en_stop_port(ifp);
|
||||
need_load = 1;
|
||||
}
|
||||
|
||||
retry:
|
||||
if (onoff) { /* enable netmap mode */
|
||||
nm_set_native_flags(na);
|
||||
} else { /* reset normal mode */
|
||||
nm_clear_native_flags(na);
|
||||
}
|
||||
if (need_load) {
|
||||
D("loading %s", ifp->if_xname);
|
||||
error = mlx4_en_start_port(ifp);
|
||||
D("start_port returns %d", error);
|
||||
if (error && onoff) {
|
||||
onoff = 0;
|
||||
goto retry;
|
||||
}
|
||||
mutex_unlock(&mdev->state_lock);
|
||||
//double_mutex_state_unlock(mdev);
|
||||
}
|
||||
// rtnl_unlock();
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Reconcile kernel and user view of the transmit ring.
|
||||
* This routine might be called frequently so it must be efficient.
|
||||
*
|
||||
|
||||
OUTGOING (txr->prod)
|
||||
Tx packets need to fill a 64-byte block with one control block and
|
||||
one descriptor (both 16-byte). Probably we need to fill the other
|
||||
two data entries in the block with NULL entries as done in rx_config().
|
||||
One can request completion reports (intr) on all entries or only
|
||||
on selected ones. The std. driver reports every 16 packets.
|
||||
|
||||
txr->prod points to the first available slot to send.
|
||||
|
||||
COMPLETION (txr->cons)
|
||||
TX events are reported through a Completion Queue (CQ) whose entries
|
||||
can be 32 or 64 bytes. In case of 64 bytes, the interesting part is
|
||||
at odd indexes. The "factor" variable does the addressing.
|
||||
|
||||
txr->cons points to the last completed block (XXX note so it is 1 behind)
|
||||
|
||||
There is no link back from the txring to the completion
|
||||
queue so we need to track it ourselves. HOWEVER mlx4_en_alloc_resources()
|
||||
uses the same index for cq and ring so tx_cq and tx_ring correspond,
|
||||
same for rx_cq and rx_ring.
|
||||
|
||||
*/
|
||||
static int
|
||||
mlx4_netmap_txsync(struct netmap_adapter *na, u_int ring_nr, int flags)
|
||||
{
|
||||
struct ifnet *ifp = na->ifp;
|
||||
struct netmap_kring *kring = &na->tx_rings[ring_nr];
|
||||
struct netmap_ring *ring = kring->ring;
|
||||
u_int nm_i; /* index into the netmap ring */
|
||||
u_int nic_i; /* index into the NIC ring */
|
||||
u_int n;
|
||||
u_int const lim = kring->nkr_num_slots - 1;
|
||||
u_int const head = kring->rhead;
|
||||
/*
|
||||
* interrupts on every tx packet are expensive so request
|
||||
* them every half ring, or where NS_REPORT is set
|
||||
*/
|
||||
u_int report_frequency = kring->nkr_num_slots >> 1;
|
||||
|
||||
struct SOFTC_T *priv = netdev_priv(ifp);
|
||||
int error = 0;
|
||||
|
||||
if (!netif_carrier_ok(ifp)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
// XXX debugging, only print if sending something
|
||||
n = (txr->prod - txr->cons - 1) & 0xffffff; // should be modulo 2^24 ?
|
||||
if (n >= txr->size) {
|
||||
RD(5, "XXXXXXXXXXX txr %d overflow: cons %u prod %u size %d delta %d",
|
||||
ring_nr, txr->cons, txr->prod, txr->size, n);
|
||||
}
|
||||
|
||||
/*
|
||||
* First part: process new packets to send.
|
||||
*/
|
||||
nm_i = kring->nr_hwcur;
|
||||
// XXX debugging, assuming lim is 2^x-1
|
||||
n = 0; // XXX debugging
|
||||
if (nm_i != head) { /* we have new packets to send */
|
||||
ND(5,"START: txr %u cons %u prod %u hwcur %u head %u tail %d send %d",
|
||||
ring_nr, txr->cons, txr->prod, kring->nr_hwcur, ring->head, kring->nr_hwtail,
|
||||
(head - nm_i) & lim);
|
||||
|
||||
// XXX see en_tx.c :: mlx4_en_xmit()
|
||||
/*
|
||||
* In netmap the descriptor has one control segment
|
||||
* and one data segment. The control segment is 16 bytes,
|
||||
* the data segment is another 16 bytes mlx4_wqe_data_seg.
|
||||
* The alignment is TXBB_SIZE (64 bytes) though, so we are
|
||||
* forced to use 64 bytes each.
|
||||
*/
|
||||
|
||||
ND(10,"=======>========== send from %d to %d at bd %d", j, k, txr->prod);
|
||||
for (n = 0; nm_i != head; n++) {
|
||||
struct netmap_slot *slot = &ring->slot[nm_i];
|
||||
u_int len = slot->len;
|
||||
uint64_t paddr;
|
||||
void *addr = PNMB(slot, &paddr);
|
||||
|
||||
/* device-specific */
|
||||
uint32_t l = txr->prod & txr->size_mask;
|
||||
struct mlx4_en_tx_desc *tx_desc = txr->buf + l * TXBB_SIZE;
|
||||
struct mlx4_wqe_ctrl_seg *ctrl = &tx_desc->ctrl;
|
||||
|
||||
NM_CHECK_ADDR_LEN(addr, len);
|
||||
|
||||
|
||||
if (slot->flags & NS_BUF_CHANGED) {
|
||||
/* buffer has changed, unload and reload map */
|
||||
// netmap_reload_map(pdev, DMA_TO_DEVICE, old_addr, addr);
|
||||
}
|
||||
slot->flags &= ~(NS_REPORT | NS_BUF_CHANGED);
|
||||
/*
|
||||
* Fill the slot in the NIC ring.
|
||||
*/
|
||||
ctrl->vlan_tag = 0; // not used
|
||||
ctrl->ins_vlan = 0; // NO
|
||||
ctrl->fence_size = 2; // used descriptor size in 16byte blocks
|
||||
// request notification. XXX later report only if NS_REPORT or not too often.
|
||||
ctrl->srcrb_flags = cpu_to_be32(MLX4_WQE_CTRL_CQ_UPDATE |
|
||||
MLX4_WQE_CTRL_SOLICITED);
|
||||
|
||||
// XXX do we need to copy the mac dst address ?
|
||||
if (1) { // XXX do we need this ?
|
||||
uint64_t mac = mlx4_en_mac_to_u64(addr);
|
||||
uint32_t mac_h = (u32) ((mac & 0xffff00000000ULL) >> 16);
|
||||
uint32_t mac_l = (u32) (mac & 0xffffffff);
|
||||
|
||||
ctrl->srcrb_flags |= cpu_to_be32(mac_h);
|
||||
ctrl->imm = cpu_to_be32(mac_l);
|
||||
}
|
||||
|
||||
tx_desc->data.addr = cpu_to_be64(paddr);
|
||||
tx_desc->data.lkey = cpu_to_be32(priv->mdev->mr.key);
|
||||
wmb(); // XXX why here ?
|
||||
tx_desc->data.byte_count = cpu_to_be32(len); // XXX crc corrupt ?
|
||||
wmb();
|
||||
ctrl->owner_opcode = cpu_to_be32(
|
||||
MLX4_OPCODE_SEND |
|
||||
((txr->prod & txr->size) ? MLX4_EN_BIT_DESC_OWN : 0) );
|
||||
txr->prod++;
|
||||
nm_i = nm_next(nm_i, lim);
|
||||
}
|
||||
kring->nr_hwcur = head;
|
||||
|
||||
/* XXX Check how to deal with nkr_hwofs */
|
||||
/* these two are always in sync. */
|
||||
wmb(); /* synchronize writes to the NIC ring */
|
||||
/* (re)start the transmitter up to slot l (excluded) */
|
||||
ND(5, "doorbell cid %d data 0x%x", txdata->cid, txdata->tx_db.raw);
|
||||
// XXX is this doorbell correct ?
|
||||
iowrite32be(txr->doorbell_qpn, txr->bf.uar->map + MLX4_SEND_DOORBELL);
|
||||
}
|
||||
// XXX debugging, only print if sent something
|
||||
if (n)
|
||||
ND(5, "SENT: txr %d cons %u prod %u hwcur %u cur %u tail %d sent %d",
|
||||
ring_nr, txr->cons, txr->prod, kring->nr_hwcur, ring->cur, kring->nr_hwtail, n);
|
||||
|
||||
/*
|
||||
* Second part: reclaim buffers for completed transmissions.
|
||||
*/
|
||||
|
||||
{
|
||||
struct mlx4_en_cq *cq = &priv->tx_cq[ring_nr];
|
||||
struct mlx4_cq *mcq = &cq->mcq;
|
||||
|
||||
int size = cq->size; // number of entries
|
||||
struct mlx4_cqe *buf = cq->buf; // base of cq entries
|
||||
uint32_t size_mask = txr->size_mask; // same in txq and cq ?.......
|
||||
uint16_t new_index, ring_index;
|
||||
int factor = priv->cqe_factor; // 1 for 64 bytes, 0 for 32 bytes
|
||||
|
||||
/*
|
||||
* Reclaim buffers for completed transmissions. The CQE tells us
|
||||
* where the consumer (NIC) is. Bit 7 of the owner_sr_opcode
|
||||
* is the ownership bit. It toggles up and down so the
|
||||
* non-bitwise XNOR trick lets us detect toggles as the ring
|
||||
* wraps around. On even rounds, the second operand is 0 so
|
||||
* we exit when the MLX4_CQE_OWNER_MASK bit is 1, viceversa
|
||||
* on odd rounds.
|
||||
*/
|
||||
new_index = ring_index = txr->cons & size_mask;
|
||||
|
||||
for (n = 0; n < 2*lim; n++) {
|
||||
uint16_t index = mcq->cons_index & size_mask;
|
||||
struct mlx4_cqe *cqe = &buf[(index << factor) + factor];
|
||||
|
||||
if (!XNOR(cqe->owner_sr_opcode & MLX4_CQE_OWNER_MASK,
|
||||
mcq->cons_index & size))
|
||||
break;
|
||||
/*
|
||||
* make sure we read the CQE after we read the
|
||||
* ownership bit
|
||||
*/
|
||||
rmb();
|
||||
|
||||
/* Skip over last polled CQE */
|
||||
new_index = be16_to_cpu(cqe->wqe_index) & size_mask;
|
||||
ND(5, "txq %d new_index %d", ring_nr, new_index);
|
||||
mcq->cons_index++;
|
||||
}
|
||||
if (n > lim) {
|
||||
D("XXXXXXXXXXX too many notifications %d", n);
|
||||
}
|
||||
/* now we have updated cons-index, notify the card. */
|
||||
/* XXX can we make it conditional ? */
|
||||
wmb();
|
||||
mlx4_cq_set_ci(mcq);
|
||||
// XXX the following enables interrupts... */
|
||||
// mlx4_en_arm_cq(priv, cq); // XXX always ?
|
||||
wmb();
|
||||
/* XXX unsigned arithmetic below */
|
||||
n = (new_index - ring_index) & size_mask;
|
||||
if (n) {
|
||||
ND(5, "txr %d completed %d packets", ring_nr, n);
|
||||
txr->cons += n;
|
||||
/* XXX watch out, index is probably modulo */
|
||||
kring->nr_hwtail = nm_prev(netmap_idx_n2k(kring, (new_index & size_mask)), lim);
|
||||
}
|
||||
if (nm_kr_txempty(kring)) {
|
||||
mlx4_en_arm_cq(priv, cq);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
nm_txsync_finalize(kring);
|
||||
return 0;
|
||||
|
||||
err:
|
||||
if (error)
|
||||
return netmap_ring_reinit(kring);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Reconcile kernel and user view of the receive ring.
|
||||
|
||||
MELLANOX:
|
||||
|
||||
the ring has prod and cons indexes, the size is a power of 2,
|
||||
size and actual_size indicate how many entries can be allocated,
|
||||
stride is the size of each entry.
|
||||
|
||||
mlx4_en_update_rx_prod_db() tells the NIC where it can go
|
||||
(to be used when new buffers are freed).
|
||||
|
||||
*/
|
||||
static int
|
||||
mlx4_netmap_rxsync(struct netmap_adapter *na, u_int ring_nr, int flags)
|
||||
{
|
||||
struct ifnet *ifp = na->ifp;
|
||||
struct netmap_kring *kring = &na->rx_rings[ring_nr];
|
||||
struct netmap_ring *ring = kring->ring;
|
||||
u_int nm_i; /* index into the netmap ring */
|
||||
u_int nic_i; /* index into the NIC ring */
|
||||
u_int n;
|
||||
u_int const lim = kring->nkr_num_slots - 1;
|
||||
u_int const head = nm_rxsync_prologue(kring);
|
||||
int force_update = (flags & NAF_FORCE_READ) || kring->nr_kflags & NKR_PENDINTR;
|
||||
|
||||
struct SOFTC_T *priv = netdev_priv(ifp);
|
||||
struct mlx4_en_rx_ring *rxr = &priv->rx_ring[ring_nr];
|
||||
|
||||
if (!priv->port_up) // XXX as in mlx4_en_process_rx_cq()
|
||||
return 0;
|
||||
|
||||
if (!netif_carrier_ok(ifp)) // XXX maybe above is redundant ?
|
||||
return 0;
|
||||
|
||||
if (head > lim)
|
||||
return netmap_ring_reinit(kring);
|
||||
|
||||
ND(5, "START rxr %d cons %d prod %d kcur %d ktail %d cur %d tail %d",
|
||||
ring_nr, rxr->cons, rxr->prod, kring->nr_hwcur, kring->nr_hwtail, ring->cur, ring->tail);
|
||||
|
||||
/*
|
||||
* First part, import newly received packets.
|
||||
*/
|
||||
|
||||
/* scan the completion queue to see what is going on.
|
||||
* The mapping is 1:1. The hardware toggles the OWNER bit in the
|
||||
* descriptor at mcq->cons_index & size_mask, which is mapped 1:1
|
||||
* to an entry in the RXR.
|
||||
* XXX there are two notifications sent to the hw:
|
||||
* mlx4_cq_set_ci(struct mlx4_cq *cq);
|
||||
* *cq->set_ci_db = cpu_to_be32(cq->cons_index & 0xffffff);
|
||||
* mlx4_en_update_rx_prod_db(rxr);
|
||||
* *ring->wqres.db.db = cpu_to_be32(ring->prod & 0xffff);
|
||||
* apparently they point to the same memory word
|
||||
* (see mlx4_en_activate_cq() ) and are initialized to 0
|
||||
* DB is the doorbell page (sec.15.1.2 ?)
|
||||
* wqres is set in mlx4_alloc_hwq_res()
|
||||
* and in turn mlx4_alloc_hwq_res()
|
||||
*/
|
||||
if (1 || netmap_no_pendintr || force_update) {
|
||||
uint16_t slot_flags = kring->nkr_slot_flags;
|
||||
|
||||
struct mlx4_en_cq *cq = &priv->rx_cq[ring_nr];
|
||||
struct mlx4_cq *mcq = &cq->mcq;
|
||||
int factor = priv->cqe_factor;
|
||||
uint32_t size_mask = rxr->size_mask;
|
||||
int size = cq->size;
|
||||
struct mlx4_cqe *buf = cq->buf;
|
||||
|
||||
nm_i = kring->nr_hwtail;
|
||||
|
||||
/* Process all completed CQEs, use same logic as in TX */
|
||||
for (n = 0; n <= 2*lim ; n++) {
|
||||
int index = mcq->cons_index & size_mask;
|
||||
struct mlx4_cqe *cqe = &buf[(index << factor) + factor];
|
||||
prefetch(cqe+1);
|
||||
if (!XNOR(cqe->owner_sr_opcode & MLX4_CQE_OWNER_MASK, mcq->cons_index & size))
|
||||
break;
|
||||
|
||||
rmb(); /* make sure data is up to date */
|
||||
ring->slot[nm_i].len = be32_to_cpu(cqe->byte_cnt) - rxr->fcs_del;
|
||||
ring->slot[nm_i].flags = slot_flags;
|
||||
mcq->cons_index++;
|
||||
nm_i = nm_next(nm_i, lim);
|
||||
}
|
||||
if (n) { /* update the state variables */
|
||||
if (n >= 2*lim)
|
||||
D("XXXXXXXXXXXXX too many received packets %d", n);
|
||||
ND(5, "received %d packets", n);
|
||||
kring->nr_hwtail = nm_i;
|
||||
rxr->cons += n;
|
||||
ND(5, "RECVD %d rxr %d cons %d prod %d kcur %d ktail %d cur %d tail %d",
|
||||
n,
|
||||
ring_nr, rxr->cons, rxr->prod, kring->nr_hwcur, kring->nr_hwtail, ring->cur, ring->tail);
|
||||
|
||||
/* XXX ack completion queue */
|
||||
mlx4_cq_set_ci(mcq);
|
||||
}
|
||||
kring->nr_kflags &= ~NKR_PENDINTR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Second part: skip past packets that userspace has released.
|
||||
*/
|
||||
nm_i = kring->nr_hwcur; /* netmap ring index */
|
||||
if (nm_i != head) { /* userspace has released some packets. */
|
||||
nic_i = netmap_idx_k2n(kring, nm_i);
|
||||
for (n = 0; nm_i != head; n++) {
|
||||
/* collect per-slot info, with similar validations
|
||||
struct netmap_slot *slot = &ring->slot[nm_i];
|
||||
uint64_t paddr;
|
||||
void *addr = PNMB(slot, &paddr);
|
||||
|
||||
struct mlx4_en_rx_desc *rx_desc = rxr->buf + (nic_i * rxr->stride);
|
||||
|
||||
if (addr == netmap_buffer_base) /* bad buf */
|
||||
goto ring_reset;
|
||||
|
||||
if (slot->flags & NS_BUF_CHANGED) {
|
||||
// netmap_reload_map(pdev, DMA_TO_DEVICE, old_addr, addr);
|
||||
slot->flags &= ~NS_BUF_CHANGED;
|
||||
}
|
||||
|
||||
/* XXX
|
||||
* The rx descriptor only contains buffer descriptors,
|
||||
* probably only the length is changed or not even that one.
|
||||
*/
|
||||
// see mlx4_en_prepare_rx_desc() and mlx4_en_alloc_frag()
|
||||
rx_desc->data[0].addr = cpu_to_be64(paddr);
|
||||
rx_desc->data[0].byte_count = cpu_to_be32(NETMAP_BUF_SIZE);
|
||||
rx_desc->data[0].lkey = cpu_to_be32(priv->mdev->mr.key);
|
||||
|
||||
#if 0
|
||||
int jj, possible_frags;
|
||||
/* we only use one fragment, so the rest is padding */
|
||||
possible_frags = (rxr->stride - sizeof(struct mlx4_en_rx_desc)) / DS_SIZE;
|
||||
for (jj = 1; jj < possible_frags; jj++) {
|
||||
rx_desc->data[jj].byte_count = 0;
|
||||
rx_desc->data[jj].lkey = cpu_to_be32(MLX4_EN_MEMTYPE_PAD);
|
||||
rx_desc->data[jj].addr = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
nm_i = nm_next(nm_i, lim);
|
||||
nic_i = nm_next(nic_i, lim);
|
||||
}
|
||||
|
||||
/* XXX note that mcq->cons_index and ring->cons are not in sync */
|
||||
wmb();
|
||||
rxr->prod += n;
|
||||
kring->nr_hwcur = head;
|
||||
|
||||
/* and now tell the system that there are more buffers available.
|
||||
* should use mlx4_en_update_rx_prod_db(rxr) but it is static in
|
||||
* en_rx.c so we do not see it here
|
||||
*/
|
||||
*rxr->wqres.db.db = cpu_to_be32(rxr->prod & 0xffff);
|
||||
|
||||
ND(5, "FREED rxr %d cons %d prod %d kcur %d ktail %d",
|
||||
ring_nr, rxr->cons, rxr->prod,
|
||||
kring->nr_hwcur, kring->nr_hwtail);
|
||||
}
|
||||
|
||||
/* tell userspace that there are new packets */
|
||||
nm_rxsync_finalize(kring);
|
||||
|
||||
return 0;
|
||||
|
||||
ring_reset:
|
||||
return netmap_ring_reinit(kring);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* If in netmap mode, attach the netmap buffers to the ring and return true.
|
||||
* Otherwise return false.
|
||||
* Called at the end of mlx4_en_start_port().
|
||||
* XXX TODO: still incomplete.
|
||||
*/
|
||||
int
|
||||
mlx4_netmap_tx_config(struct SOFTC_T *priv, int ring_nr)
|
||||
{
|
||||
struct netmap_adapter *na = NA(priv->dev);
|
||||
struct netmap_slot *slot;
|
||||
struct mlx4_en_cq *cq;
|
||||
|
||||
ND(5, "priv %p ring_nr %d", priv, ring_nr);
|
||||
|
||||
if (!na || !(na->na_flags & NAF_NATIVE_ON)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
CONFIGURE TX RINGS IN NETMAP MODE
|
||||
little if anything to do
|
||||
The main code does
|
||||
mlx4_en_activate_cq()
|
||||
mlx4_en_activate_tx_ring()
|
||||
<Set initial ownership of all Tx TXBBs to SW (1)>
|
||||
|
||||
*/
|
||||
slot = netmap_reset(na, NR_TX, ring_nr, 0);
|
||||
if (!slot)
|
||||
return 0; // not in netmap mode;
|
||||
ND(5, "init tx ring %d with %d slots (driver %d)", ring_nr,
|
||||
na->num_tx_desc,
|
||||
priv->tx_ring[ring_nr].size);
|
||||
/* enable interrupts on the netmap queues */
|
||||
cq = &priv->tx_cq[ring_nr]; // derive from the txring
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
mlx4_netmap_rx_config(struct SOFTC_T *priv, int ring_nr)
|
||||
{
|
||||
struct netmap_adapter *na = NA(priv->dev);
|
||||
struct netmap_slot *slot;
|
||||
struct mlx4_en_rx_ring *rxr;
|
||||
struct netmap_kring *kring;
|
||||
int i, j, possible_frags;
|
||||
|
||||
if (!na || !(na->na_flags & NAF_NATIVE_ON)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* on the receive ring, must set buf addresses into the slots.
|
||||
|
||||
The ring is activated by mlx4_en_activate_rx_rings(), near the end
|
||||
the rx ring is also 'started' with mlx4_en_update_rx_prod_db()
|
||||
so we patch into that routine.
|
||||
|
||||
*/
|
||||
slot = netmap_reset(na, NR_RX, ring_nr, 0);
|
||||
if (!slot) // XXX should not happen
|
||||
return 0;
|
||||
kring = &na->rx_rings[ring_nr];
|
||||
rxr = &priv->rx_ring[ring_nr];
|
||||
ND(20, "ring %d slots %d (driver says %d) frags %d stride %d", ring_nr,
|
||||
kring->nkr_num_slots, rxr->actual_size, priv->num_frags, rxr->stride);
|
||||
rxr->prod--; // XXX avoid wraparounds ?
|
||||
if (kring->nkr_num_slots != rxr->actual_size) {
|
||||
D("mismatch between slots and actual size, %d vs %d",
|
||||
kring->nkr_num_slots, rxr->actual_size);
|
||||
return 1; // XXX error
|
||||
}
|
||||
possible_frags = (rxr->stride - sizeof(struct mlx4_en_rx_desc)) / DS_SIZE;
|
||||
RD(1, "stride %d possible frags %d descsize %d DS_SIZE %d", rxr->stride, possible_frags, (int)sizeof(struct mlx4_en_rx_desc), (int)DS_SIZE );
|
||||
/* then fill the slots with our entries */
|
||||
for (i = 0; i < kring->nkr_num_slots; i++) {
|
||||
uint64_t paddr;
|
||||
struct mlx4_en_rx_desc *rx_desc = rxr->buf + (i * rxr->stride);
|
||||
|
||||
PNMB(slot + i, &paddr);
|
||||
|
||||
// see mlx4_en_prepare_rx_desc() and mlx4_en_alloc_frag()
|
||||
rx_desc->data[0].addr = cpu_to_be64(paddr);
|
||||
rx_desc->data[0].byte_count = cpu_to_be32(NETMAP_BUF_SIZE);
|
||||
rx_desc->data[0].lkey = cpu_to_be32(priv->mdev->mr.key);
|
||||
|
||||
/* we only use one fragment, so the rest is padding */
|
||||
for (j = 1; j < possible_frags; j++) {
|
||||
rx_desc->data[j].byte_count = 0;
|
||||
rx_desc->data[j].lkey = cpu_to_be32(MLX4_EN_MEMTYPE_PAD);
|
||||
rx_desc->data[j].addr = 0;
|
||||
}
|
||||
}
|
||||
RD(5, "ring %d done", ring_nr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
mlx4_netmap_config(struct netmap_adapter *na,
|
||||
u_int *txr, u_int *txd, u_int *rxr, u_int *rxd)
|
||||
{
|
||||
struct net_device *ifp = na->ifp;
|
||||
struct SOFTC_T *priv = netdev_priv(ifp);
|
||||
|
||||
*txr = priv->tx_ring_num;
|
||||
*txd = priv->tx_ring[0].size;
|
||||
|
||||
|
||||
*rxr = priv->rx_ring_num;
|
||||
if (*txr > *rxr) {
|
||||
D("using only %d out of %d tx queues", *rxr, *txr);
|
||||
*txr = *rxr;
|
||||
}
|
||||
*rxd = priv->rx_ring[0].size;
|
||||
D("txr %d txd %d bufsize %d -- rxr %d rxd %d act %d bufsize %d",
|
||||
*txr, *txd, priv->tx_ring[0].buf_size,
|
||||
*rxr, *rxd, priv->rx_ring[0].actual_size,
|
||||
priv->rx_ring[0].buf_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The attach routine, called near the end of mlx4_en_init_netdev(),
|
||||
* fills the parameters for netmap_attach() and calls it.
|
||||
* It cannot fail, in the worst case (such as no memory)
|
||||
* netmap mode will be disabled and the driver will only
|
||||
* operate in standard mode.
|
||||
*
|
||||
* XXX TODO:
|
||||
* at the moment use a single lock, and only init a max of 4 queues.
|
||||
*/
|
||||
static void
|
||||
mlx4_netmap_attach(struct SOFTC_T *priv)
|
||||
{
|
||||
struct netmap_adapter na;
|
||||
struct net_device *dev = priv->dev;
|
||||
int rxq, txq;
|
||||
|
||||
bzero(&na, sizeof(na));
|
||||
|
||||
na.ifp = dev;
|
||||
rxq = priv->rx_ring_num;
|
||||
txq = priv->tx_ring_num;
|
||||
/* this card has 1k tx queues, so better limit the number */
|
||||
if (rxq > 16)
|
||||
rxq = 16;
|
||||
if (txq > rxq)
|
||||
txq = rxq;
|
||||
if (txq < 1 && rxq < 1)
|
||||
txq = rxq = 1;
|
||||
na.num_tx_rings = txq;
|
||||
na.num_rx_rings = rxq;
|
||||
na.num_tx_desc = priv->tx_ring[0].size;
|
||||
na.num_rx_desc = priv->rx_ring[0].size;
|
||||
na.nm_txsync = mlx4_netmap_txsync;
|
||||
na.nm_rxsync = mlx4_netmap_rxsync;
|
||||
na.nm_register = mlx4_netmap_reg;
|
||||
na.nm_config = mlx4_netmap_config;
|
||||
netmap_attach(&na);
|
||||
}
|
||||
#endif /* NETMAP_MLX4_MAIN */
|
||||
/* end of file */
|
1257
netmap/LINUX/netmap_linux.c
Normal file
1257
netmap/LINUX/netmap_linux.c
Normal file
File diff suppressed because it is too large
Load Diff
68
netmap/LINUX/netmap_set_adapter.sh
Executable file
68
netmap/LINUX/netmap_set_adapter.sh
Executable file
@ -0,0 +1,68 @@
|
||||
#!/bin/sh
|
||||
|
||||
#set -x # for debugging
|
||||
|
||||
if [ -z "$NMSRC" ]; then
|
||||
NMSRC=~/netmap-release
|
||||
fi
|
||||
DRIVER="ixgbe"
|
||||
#IF="eth0" # force an interface
|
||||
|
||||
if [ ! -f ${NMSRC}/LINUX/netmap_lin.ko ]; then
|
||||
echo "LINUX/netmap_lin.ko missing. Please compile netmap."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f ${NMSRC}/LINUX/${DRIVER}/${DRIVER}.ko ]; then
|
||||
echo "LINUX/${DRIVER}/${DRIVER}.ko missing."
|
||||
echo "Please compile netmap or make sure to have netmap support for ${DRIVER}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
NMLOADED=$(lsmod | grep netmap_lin | wc -l)
|
||||
DRVLOADED=$(lsmod | grep "${DRIVER}" | wc -l)
|
||||
|
||||
# Unload the driver
|
||||
if [ $DRVLOADED != "0" ]; then
|
||||
sudo rmmod "$DRIVER"
|
||||
fi
|
||||
|
||||
# Load netmap
|
||||
if [ $NMLOADED == "0" ]; then
|
||||
sudo insmod ${NMSRC}/LINUX/netmap_lin.ko
|
||||
fi
|
||||
|
||||
if [ "$1" == "g" ]; then
|
||||
# In order to use generic netmap adapter, load the original driver module, that doesn't
|
||||
# have netmap support
|
||||
sudo modprobe ${DRIVER}
|
||||
echo "Generic netmap adapter."
|
||||
else
|
||||
# Use the driver modified with netmap support
|
||||
sudo insmod ${NMSRC}/LINUX/${DRIVER}/${DRIVER}.ko
|
||||
echo "Native netmap adapter."
|
||||
fi
|
||||
|
||||
# Wait a bit for interface name changing
|
||||
sleep 2
|
||||
|
||||
# Find all interfaces
|
||||
IFLIST=$(ip link | grep -o "^[0-9]\+: [^:]\+" | awk '{print $2}')
|
||||
IFLIST=$(echo ${IFLIST})
|
||||
|
||||
# Find the interface that match the driver $DRIVER
|
||||
for i in $IFLIST; do
|
||||
drv=$(sudo ethtool -i $i 2> /dev/null | grep "driver" | awk '{print $2}')
|
||||
if [ "$drv" == "$DRIVER" ]; then
|
||||
IF=$i
|
||||
echo " Found interface \"${IF}\""
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$IF" == "" ]; then
|
||||
echo "No interface using ${DRIVER} driver was found."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
sudo ip link set ${IF} up
|
||||
|
1
netmap/LINUX/patches
Symbolic link
1
netmap/LINUX/patches
Symbolic link
@ -0,0 +1 @@
|
||||
final-patches
|
3
netmap/LINUX/scripts/help
Executable file
3
netmap/LINUX/scripts/help
Executable file
@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
sed -n 's/^## \?//p' $1 | fmt
|
82
netmap/LINUX/scripts/linux-pktgen.sh
Executable file
82
netmap/LINUX/scripts/linux-pktgen.sh
Executable file
@ -0,0 +1,82 @@
|
||||
#!/bin/sh
|
||||
|
||||
#set -x
|
||||
|
||||
|
||||
function pgset()
|
||||
{
|
||||
local result
|
||||
|
||||
echo $1 > ${PGDEV}
|
||||
|
||||
result=$(cat $PGDEV | fgrep "Result: OK:")
|
||||
if [ "$result" = "" ]; then
|
||||
cat $PGDEV | fgrep "Result:"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
##################### Script configuration ######################
|
||||
N="$1" # number of TX kthreads minus one
|
||||
if [ -z "$1" ]; then
|
||||
N=0
|
||||
fi
|
||||
NCPUS="7" # number of CPUs on your machine minus one
|
||||
IF="enp1s0f1" # network interface to test
|
||||
DST_IP="10.216.8.1" # destination IP address
|
||||
DST_MAC="00:1b:21:80:e7:d9" # destination MAC address
|
||||
PKT_SIZE="60" # packet size
|
||||
PKT_COUNT="10000000" # number of packets to send
|
||||
CLONE_SKB="10000" # how many times a sk_buff is recycled
|
||||
|
||||
|
||||
# Load pktgen kernel module
|
||||
modprobe pktgen
|
||||
|
||||
|
||||
# Clean the configuration for all the CPU-kthread (from 0 to ${NCPUS})
|
||||
IDX=$(seq 0 1 ${NCPUS})
|
||||
for cpu in ${IDX}; do
|
||||
PGDEV="/proc/net/pktgen/kpktgend_${cpu}"
|
||||
echo "Removing all devices (${cpu})"
|
||||
pgset "rem_device_all"
|
||||
done
|
||||
|
||||
IDX=$(seq 0 1 ${N})
|
||||
for cpu in ${IDX}; do
|
||||
# kthread-device configuration
|
||||
PGDEV="/proc/net/pktgen/kpktgend_${cpu}"
|
||||
echo "Configuring $PGDEV"
|
||||
echo "Adding ${IF}@${cpu}"
|
||||
pgset "add_device ${IF}@${cpu}"
|
||||
|
||||
# Packets/mode configuration
|
||||
PGDEV="/proc/net/pktgen/${IF}@${cpu}"
|
||||
echo "Configuring $PGDEV"
|
||||
pgset "count ${PKT_COUNT}"
|
||||
pgset "clone_skb ${CLONE_SKB}"
|
||||
pgset "pkt_size ${PKT_SIZE}"
|
||||
pgset "delay 0"
|
||||
pgset "dst $DST_IP"
|
||||
pgset "dst_mac $DST_MAC"
|
||||
pgset "flag QUEUE_MAP_CPU"
|
||||
|
||||
echo ""
|
||||
done
|
||||
|
||||
|
||||
# Run
|
||||
PGDEV="/proc/net/pktgen/pgctrl"
|
||||
echo "Running... Ctrl-C to stop"
|
||||
pgset "start"
|
||||
echo "Done."
|
||||
|
||||
# Show results
|
||||
NUMS=""
|
||||
for cpu in ${IDX}; do
|
||||
TMP=$(cat /proc/net/pktgen/${IF}@${cpu} | grep -o "[0-9]\+pps" | grep -o "[0-9]\+")
|
||||
echo "$cpu $TMP"
|
||||
NUMS="${NUMS} ${TMP}"
|
||||
done
|
||||
|
||||
echo "Total TX rate: $(echo $NUMS | tr ' ' '+' | bc)"
|
428
netmap/LINUX/scripts/np
Executable file
428
netmap/LINUX/scripts/np
Executable file
@ -0,0 +1,428 @@
|
||||
#!/bin/bash
|
||||
## Manage linux driver patches for netmap.
|
||||
## usage (from the dir containing the Makefile):
|
||||
##
|
||||
## scripts/np <action> [args...]
|
||||
##
|
||||
## where <action> is any of the functions below.
|
||||
##
|
||||
|
||||
[ -f scripts/conf ] && source scripts/conf
|
||||
|
||||
## The following enviroment variables must be set:
|
||||
##
|
||||
## GITDIR: the absolute path of the netmap linux
|
||||
## git repository, containing all the required netmap-*
|
||||
## branches.
|
||||
[ -n "$GITDIR" -a -d "$GITDIR/.git" ] || {
|
||||
echo "GITDIR not set or not valid" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
NETMAP_BRANCH=${NETMAP_BRANCH:-master}
|
||||
|
||||
function error {
|
||||
echo "$@" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
function get-params {
|
||||
local params=$1; shift
|
||||
err_msg="$PROGNAME $COMMAND $(echo $params| perl -pe 's/\S+/<$&>/g')"
|
||||
local param
|
||||
for param in $params; do
|
||||
[[ -z "$@" ]] && error "$err_msg"
|
||||
pname=$(echo -n $param | perl -pe 's/\W/_/g')
|
||||
eval $pname="$1"
|
||||
shift
|
||||
done
|
||||
[[ -n "$@" ]] && error "$err_msg"
|
||||
}
|
||||
|
||||
##
|
||||
## LINUX_SOURCES: the absolute path of a
|
||||
## directory used to store all required linux-* source trees
|
||||
## (The script will extract linux-x.y.z from GITDIR if it needs
|
||||
## it and $LINUX_SOURCES does not already contain it).
|
||||
##
|
||||
## LINUX_CONFIGS: the absolute path of a
|
||||
## directory containing the configuration files for
|
||||
## the linux kernel. The file for version x must be named
|
||||
## config-x. config-all can be used as a default.
|
||||
##
|
||||
## The configuration variables can be put in scripts/conf.
|
||||
##
|
||||
|
||||
##
|
||||
## Available actions:
|
||||
##
|
||||
|
||||
##
|
||||
## driver-path <driver> <version>
|
||||
## retrieves the path of <driver> in the linux sources
|
||||
## for version <version>. The path is output to stdout.
|
||||
## It uses a local cache to minimize the expensive
|
||||
## file system search.
|
||||
function driver-path()
|
||||
{
|
||||
get-params "driver version" "$@"
|
||||
|
||||
cat cache/$version/$driver/path 2>/dev/null && return
|
||||
local kern=$(get-kernel $version)
|
||||
mkdir -p cache/$version/$driver
|
||||
(
|
||||
cd $kern
|
||||
find drivers/net -name $driver
|
||||
) | tee cache/$version/$driver/path
|
||||
}
|
||||
|
||||
|
||||
##
|
||||
## get-patch [-c] <driver> <version>
|
||||
## extract the netmap patch for the given <driver> and the
|
||||
## given kernel <version>. The patch is stored in tmp-patches
|
||||
## and the name of the patch is output to stdout.
|
||||
## If a patch with the same name already exists in tmp-patches
|
||||
## it is overwritten, unless the -c option is used,
|
||||
## in which case the existing patch is kept (the patch name is still output).
|
||||
function get-patch()
|
||||
{
|
||||
local use_cache
|
||||
[ "$1" = -c ] && { use_cache=1; shift; }
|
||||
|
||||
get-params "driver version" "$@"
|
||||
|
||||
# convert kernel version to fixed notation
|
||||
local v1=$(scripts/vers $version -c)
|
||||
# compute next kernel version (in fixed notation)
|
||||
local v2=$(scripts/vers $version -i -c)
|
||||
local patchname=diff--$driver--$v1--$v2
|
||||
local out=tmp-patches/$patchname
|
||||
[ -n "$use_cache" -a -s $out ] && { echo $out; return; }
|
||||
local drvpath=$(driver-path $driver $version)
|
||||
[ -n "$drvpath" ] || return
|
||||
local drvdir=$(dirname $drvpath)
|
||||
(
|
||||
cd $GITDIR
|
||||
git diff --relative=$drvdir v$version..netmap-$version -- $drvpath
|
||||
) > $out
|
||||
# an empty patch means no netmap support for this driver
|
||||
[ -s $out ] || { rm $out; return 1; }
|
||||
echo $out
|
||||
return 0;
|
||||
}
|
||||
|
||||
##
|
||||
## get-range <driver> <version1> <version2>
|
||||
## extracts the netmap patches for the given <driver> for
|
||||
## all the kernel versions from <version1> (included) to
|
||||
## <version2> (excluded). All patches are stored in tmp-patches
|
||||
## and their names are output to stdout.
|
||||
function get-range()
|
||||
{
|
||||
get-params "driver version1 version2" "$@"
|
||||
|
||||
local v=$version1
|
||||
# while version is less than $version2
|
||||
while scripts/vers -b $v $version2 -L; do
|
||||
get-patch $driver $v
|
||||
# compute next version
|
||||
v=$(scripts/vers $v -i)
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
##
|
||||
## get-src <driver> <version> <dest>
|
||||
## copies the original sources of the given <driver>,
|
||||
## from the given kernel <version> to the given <dest>
|
||||
## directory.
|
||||
## It uses a local cache to minimize the expensive
|
||||
## checkouts in GITDIR.
|
||||
function get-src()
|
||||
{
|
||||
get-params "driver version dest" "$@"
|
||||
|
||||
local kern=$(get-kernel $version)
|
||||
local src=$(driver-path $driver $version)
|
||||
cp -r $kern/$src $dest
|
||||
}
|
||||
|
||||
|
||||
##
|
||||
## extend <patch> <version>
|
||||
## checks wether the range of applicability of the
|
||||
## given <patch> can be extented to include <version>.
|
||||
## It returns 0 on success and 1 on failure.
|
||||
function extend()
|
||||
{
|
||||
get-params "patch version" "$@"
|
||||
|
||||
local _patch=$(realpath $patch)
|
||||
# extract the driver name from the patch name
|
||||
local driver=$(scripts/vers $_patch -s -p -p)
|
||||
local tmpdir1=$(mktemp -d)
|
||||
local tmpdir2=$(mktemp -d)
|
||||
trap "rm -rf $tmpdir1 $tmpdir2" 0
|
||||
# we get the driver sources for the given <version> and
|
||||
# we apply two patches separately:
|
||||
# i) the given <patch>;
|
||||
# ii) the proper patch from GITDIR.
|
||||
# We declare <patch> to be extendable if
|
||||
# - it is still applicable AND
|
||||
# - we obtain the same files from i) and ii) (ignoring whitespace)
|
||||
get-src $driver $version $tmpdir1
|
||||
get-src $driver $version $tmpdir2
|
||||
(
|
||||
cd $tmpdir1
|
||||
patch --no-backup-if-mismatch -p1 < $_patch >/dev/null 2>&1
|
||||
) || return 1
|
||||
local patch2=$(get-patch -c $driver $version)
|
||||
patch2=$(realpath $patch2)
|
||||
(
|
||||
cd $tmpdir2
|
||||
patch -p1 < $patch2 >/dev/null 2>&1
|
||||
) # this will certainly apply
|
||||
diff -qbBr $tmpdir1 $tmpdir2 >/dev/null || return 1
|
||||
return 0
|
||||
}
|
||||
|
||||
##
|
||||
## minimize <driver>
|
||||
## tries to minimize the number of patch files for the given
|
||||
## <driver>. It uses the patches currently found in tmp-patches
|
||||
## and stores the resulting patches in final-patches.
|
||||
## If final-patches already contained patches for <driver>,
|
||||
## they are deleted first.
|
||||
function minimize()
|
||||
{
|
||||
get-params "driver" "$@"
|
||||
|
||||
mkdir -p final-patches
|
||||
local drv=$(basename $driver)
|
||||
local patches=$(ls tmp-patches/diff--$drv--* 2>/dev/null)
|
||||
[ -n "$patches" ] || return 1
|
||||
# put the patch names in $1, $2, ...
|
||||
set $patches
|
||||
rm -f final-patches/diff--$drv--*
|
||||
# the original patches (in tmp-patches) are ordered by version number.
|
||||
# We consider one patch in turn (the 'pivot') and try
|
||||
# to extend its range to cover the range of the next
|
||||
# patch. If this succedes, the merged patch is the new
|
||||
# pivot, otherwise the current pivot is output and the
|
||||
# next patch becomes the new pivot. The process
|
||||
# is repeated until there are no more patches to consider.
|
||||
local pivot=$1
|
||||
[ -n "$pivot" -a -e "$pivot" ] || return 1
|
||||
# extract the left end and right end of the pivot's range
|
||||
local ple=$(scripts/vers $pivot -s -p -C)
|
||||
local pre=$(scripts/vers $pivot -s -C)
|
||||
while [ -n "$pivot" ]; do
|
||||
shift
|
||||
if [ -n "$1" ]; then
|
||||
# extract the left end and right end of the next patch
|
||||
local nle=$(scripts/vers $1 -s -p -C)
|
||||
local nre=$(scripts/vers $1 -s -C)
|
||||
# we admit no gaps in the range
|
||||
if [ $pre = $nle ] && extend $pivot $nle; then
|
||||
pre=$nre
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
# either out of patches or failed merge.
|
||||
# Compute the file name of the current pivot and store
|
||||
# the patch in its final location
|
||||
out=$(scripts/vers diff $drv $ple -c $pre -c -S4)
|
||||
cp $pivot final-patches/$out
|
||||
# the new pivot becames the next patch (if any)
|
||||
pivot=$1
|
||||
pre=$nre
|
||||
ple=$nle
|
||||
done
|
||||
return 0
|
||||
}
|
||||
|
||||
##
|
||||
## infty <driver> <version>
|
||||
## if final-patches contains a patch for <driver> with a range
|
||||
## ending in <version>, extend it to infinity.
|
||||
## Do nothing otherwise.
|
||||
function infty()
|
||||
{
|
||||
get-params "driver version" "$@"
|
||||
|
||||
local drv=$(basename $driver)
|
||||
# convert kernel version to fixed notation
|
||||
local v=$(scripts/vers $version -c)
|
||||
local last=$(ls final-patches/diff--$drv--*--$v 2>/dev/null|tail -n1)
|
||||
[ -n "$last" ] || return 1
|
||||
mv -n $last $(scripts/vers $last -s -p 99999 -S4) 2>/dev/null
|
||||
}
|
||||
|
||||
function get-kernel()
|
||||
{
|
||||
get-params "version" "$@"
|
||||
|
||||
local dst="$(realpath $LINUX_SOURCES)/linux-$version"
|
||||
|
||||
[ -d $dst ] && { echo $dst; return; }
|
||||
|
||||
mkdir -p $dst
|
||||
|
||||
(
|
||||
cd $GITDIR
|
||||
git archive v$v | tar xf - -C $dst
|
||||
)
|
||||
echo $dst
|
||||
}
|
||||
|
||||
|
||||
##
|
||||
## build-prep <version>
|
||||
## prepare the linux tree for <version> to be ready
|
||||
## for external modules compilation.
|
||||
## The tree is put in $LINUX_SOURCES/linux-<version> and the
|
||||
## configuration is obtained from $LINUX_CONFIGS/config-<version>
|
||||
## (or $LINUX_CONFIGS/config-all by default).
|
||||
## Errors are logged to $LINUX_CONFIGS/linux-<version>.log.
|
||||
## If $LINUX_SOURCES/linux-<version> already exists,
|
||||
## nothing is done.
|
||||
## In all cases, the absolute path of linux-<version> is
|
||||
## output.
|
||||
function build-prep()
|
||||
{
|
||||
get-params "version" "$@"
|
||||
|
||||
local dst=$(get-kernel $version)
|
||||
|
||||
exec 3>&1 4>&2 >$dst.log 2>&1
|
||||
cp $LINUX_CONFIGS/config-$v $dst/.config 2>/dev/null ||
|
||||
cp $LINUX_CONFIGS/config-all $dst/.config
|
||||
(
|
||||
cd $dst
|
||||
yes '' | make oldconfig
|
||||
make modules_prepare
|
||||
)
|
||||
exec 1>&3 2>&4
|
||||
echo $dst
|
||||
}
|
||||
|
||||
##
|
||||
## check-patch <patch>
|
||||
## check that the given <patch> applies and compiles without
|
||||
## error for all its declared range of applicability.
|
||||
## Errors are logged to log/<patch>.
|
||||
function check-patch()
|
||||
{
|
||||
get-params "patch" "$@"
|
||||
|
||||
# extract the left version
|
||||
local v1=$(scripts/vers $patch -s -p -C)
|
||||
# extract the right version
|
||||
local v2=$(scripts/vers $patch -s -C)
|
||||
# extract the driver name
|
||||
local driver=$(scripts/vers $patch -s -p -p)
|
||||
local p=$(realpath $patch)
|
||||
mkdir -p log
|
||||
local log="$(realpath log)/$(basename $patch)"
|
||||
local nmcommit=$(cd ..; git show-ref -s heads/$NETMAP_BRANCH)
|
||||
|
||||
echo -n $patch...
|
||||
|
||||
while scripts/vers -b $v1 $v2 -L; do
|
||||
# cache lookup
|
||||
local cache=cache/$v1/$driver
|
||||
local cpatch=$cache/patch
|
||||
local cnmcommit=$cache/nmcommit
|
||||
local cstatus=$cache/status
|
||||
local clog=$cache/log
|
||||
if [ -f $cpatch ] &&
|
||||
cmp -s $cpatch $patch &&
|
||||
[ "$nmcommit" = "$(cat $cnmcommit)" ]; then
|
||||
cp $clog $log
|
||||
ok=$(cat $cstatus)
|
||||
else
|
||||
# update cache
|
||||
cp $patch $cpatch
|
||||
echo $nmcommit > $cnmcommit
|
||||
|
||||
local ksrc=$(build-prep $v1)
|
||||
local tmpdir=$(mktemp -d)
|
||||
trap "rm -rf $tmpdir" 0
|
||||
(cd ..; git archive $NETMAP_BRANCH | tar xf - -C $tmpdir )
|
||||
pushd $tmpdir/LINUX >/dev/null
|
||||
mkdir single-patch
|
||||
rm patches
|
||||
ln -s single-patch patches
|
||||
cp $p single-patch
|
||||
ok=false
|
||||
make KSRC=$ksrc >$log 2>&1 && ok=true
|
||||
popd >/dev/null
|
||||
cp $log $clog
|
||||
fi
|
||||
[ $ok = true ] || { echo FAILED; echo false > $cstatus; return 1; }
|
||||
echo true > $cstatus
|
||||
rm -rf $tmpdir
|
||||
# compute next version
|
||||
v1=$(scripts/vers $v1 -i)
|
||||
done
|
||||
echo OK
|
||||
}
|
||||
|
||||
##
|
||||
## build-check <driver>
|
||||
## do a check-patch for all the patches of <driver> that are
|
||||
## currently in tmp-patches. Patches that fail the check
|
||||
## are moved to failed-patches.
|
||||
function build-check()
|
||||
{
|
||||
get-params "driver" "$@"
|
||||
|
||||
mkdir -p failed-patches
|
||||
local drv=$(basename $driver)
|
||||
local patches=$(ls tmp-patches/diff--$drv--* 2>/dev/null)
|
||||
local p
|
||||
for p in $patches; do
|
||||
check-patch $p || mv $p failed-patches
|
||||
done
|
||||
}
|
||||
|
||||
##
|
||||
## forall <cmd> [args...]
|
||||
## exec <cmd> <driver> [args...] for all known drivers.
|
||||
function forall()
|
||||
{
|
||||
local cmd=$1
|
||||
shift
|
||||
# we obtain the value of DRIVER_SRC from the makefile
|
||||
# (the +% target is defined in our Makefile and prints
|
||||
# the contents of variable %)
|
||||
local driver_srcs=$(make +DRIVER_SRCS)
|
||||
|
||||
local driver
|
||||
for driver in $driver_srcs; do
|
||||
$cmd $(basename $driver) "$@"
|
||||
done
|
||||
}
|
||||
|
||||
mkdir -p tmp-patches
|
||||
|
||||
PROGNAME=$0
|
||||
|
||||
[ -n "$1" ] || {
|
||||
scripts/help $PROGNAME;
|
||||
exit 1
|
||||
}
|
||||
|
||||
COMMAND=$1; shift
|
||||
case $COMMAND in
|
||||
*-all)
|
||||
forall ${COMMAND%-all} "$@"
|
||||
;;
|
||||
-[hH]|--help|-help|help)
|
||||
scripts/help $PROGNAME
|
||||
;;
|
||||
*)
|
||||
$COMMAND "$@"
|
||||
;;
|
||||
esac
|
162
netmap/LINUX/scripts/vers
Executable file
162
netmap/LINUX/scripts/vers
Executable file
@ -0,0 +1,162 @@
|
||||
#!/usr/bin/perl
|
||||
## Simple stack-based RPN calculator for linux version numbers.
|
||||
## Usage:
|
||||
##
|
||||
## scripts/vers [operand|operation ...]
|
||||
##
|
||||
## Operations all start with '-', everything else is an operand
|
||||
## and is pushed on the stack as-is.
|
||||
## When all arguments have been processed, the content of the
|
||||
## top of the stack is printed on stdout and the script ends.
|
||||
##
|
||||
## Available operations:
|
||||
|
||||
sub badversion
|
||||
{
|
||||
my $v = shift;
|
||||
die "Bad version $v";
|
||||
}
|
||||
|
||||
sub conv
|
||||
{
|
||||
my $v = shift;
|
||||
|
||||
return sprintf "%x%02x%02x", (split /\./, $v);
|
||||
}
|
||||
|
||||
|
||||
sub rconv
|
||||
{
|
||||
my $v = shift;
|
||||
|
||||
$v =~ /(.*)(..)(..)$/;
|
||||
if ($1 > 2 && (hex $3) == 0) {
|
||||
return sprintf "%d.%d", (hex $1), (hex $2);
|
||||
}
|
||||
return sprintf "%d.%d.%d", (hex $1), (hex $2), (hex $3);
|
||||
}
|
||||
|
||||
sub next
|
||||
{
|
||||
my $v = shift;
|
||||
my ($may, $min, $sub) = split /\./, $v;
|
||||
|
||||
if ($may < 2 || ($may == 2 && $min != 6)) {
|
||||
&badversion($v);
|
||||
}
|
||||
if ($may == 2) {
|
||||
if ($sub < 39) {
|
||||
return "2.6." . ($sub + 1);
|
||||
} elsif ($sub == 39) {
|
||||
return "3.0";
|
||||
} else {
|
||||
&badversion($v);
|
||||
}
|
||||
} else {
|
||||
return "$may." . ($min + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@ARGV or do { system("scripts/help $0"); exit 1; };
|
||||
|
||||
for (@ARGV) {
|
||||
##
|
||||
## -b (nullary) suppress normal output. On exit, return 1
|
||||
## if stack top is "false", 0 otherwise.
|
||||
/^-b$/ && do {
|
||||
$silent=1;
|
||||
next;
|
||||
};
|
||||
##
|
||||
## -c (unary) convert from dot to fixed notation
|
||||
/^-c$/ && do {
|
||||
$v = pop @stack;
|
||||
push @stack, &conv($v);
|
||||
next;
|
||||
};
|
||||
##
|
||||
## -C (unary) convert from fixed to dot notation
|
||||
/^-C$/ && do {
|
||||
$v = pop @stack;
|
||||
push @stack, &rconv($v);
|
||||
next;
|
||||
};
|
||||
##
|
||||
## -i (unary) increment version number
|
||||
## (must be in dot notation)
|
||||
/^-i$/ && do {
|
||||
$v = pop @stack;
|
||||
push @stack, &next($v);
|
||||
next;
|
||||
};
|
||||
##
|
||||
## -s (unary) assume the stack top is a
|
||||
## string containing several fields separated
|
||||
## by '--'. Replace the stack top with these
|
||||
## fields (last on top)
|
||||
/^-s$/ && do {
|
||||
$v = pop @stack;
|
||||
push @stack, split /--/, $v;
|
||||
next;
|
||||
};
|
||||
##
|
||||
## -SN (N-ary) pop N elements from the stack,
|
||||
## join them using '--' as a separator
|
||||
## (top as last) and push the resulting
|
||||
## string
|
||||
/^-S(\d+)$/ && do {
|
||||
$n = $1;
|
||||
@t = @stack[-$n..-1];
|
||||
while ($n--) {
|
||||
pop @stack;
|
||||
}
|
||||
push @stack, (join '--', @t);
|
||||
next;
|
||||
};
|
||||
##
|
||||
## -p (unary) pop
|
||||
/^-p$/ && do {
|
||||
pop @stack;
|
||||
next;
|
||||
};
|
||||
##
|
||||
## -l (binary) push "true" if first version
|
||||
## number is stricly less then second version
|
||||
## number (versions in fixed notation)
|
||||
##
|
||||
## -L (binary) like -l, but for version numbers
|
||||
## in dot notation
|
||||
/^-[lL]$/ && do {
|
||||
$v1 = pop @stack;
|
||||
$v2 = pop @stack;
|
||||
/^-L$/ && do {
|
||||
$v1 = &conv($v1);
|
||||
$v2 = &conv($v2);
|
||||
};
|
||||
push @stack, (($v2 lt $v1) ? "true" : "false");
|
||||
next;
|
||||
};
|
||||
##
|
||||
## -a (binary) logical and. Arguments must be
|
||||
## either "true" or "false".
|
||||
/^-a$/ && do {
|
||||
$v1 = pop @stack;
|
||||
$v2 = pop @stack;
|
||||
push @stack, (($v1 eq "true" && $v2 eq "true") ? "true" : "false");
|
||||
next;
|
||||
};
|
||||
##
|
||||
## -n (unary) logical not. Argument must be
|
||||
## either "true" or "false".
|
||||
/^-n$/ && do {
|
||||
$v1 = pop @stack;
|
||||
push @stack, (($v1 eq "true") ? "false" : "true");
|
||||
next;
|
||||
};
|
||||
push @stack, $_;
|
||||
}
|
||||
$v = pop @stack;
|
||||
if ($silent) {
|
||||
exit ($v eq "false");
|
||||
}
|
||||
print "$v\n";
|
538
netmap/LINUX/virtio_netmap.h
Normal file
538
netmap/LINUX/virtio_netmap.h
Normal file
@ -0,0 +1,538 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Vincenzo Maffione. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <bsd_glue.h>
|
||||
#include <net/netmap.h>
|
||||
#include <netmap/netmap_kern.h>
|
||||
|
||||
|
||||
#define SOFTC_T virtnet_info
|
||||
|
||||
static int virtnet_close(struct ifnet *ifp);
|
||||
static int virtnet_open(struct ifnet *ifp);
|
||||
static void free_receive_bufs(struct virtnet_info *vi);
|
||||
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
|
||||
/* Before 2.6.35 there was no net_device.num_rx_queues, so we assume 1. */
|
||||
#define DEV_NUM_RX_QUEUES(_netdev) 1
|
||||
/* A scatterlist struct is needed by functions that invoke
|
||||
virtqueue_add_buf() methods, but before 2.6.35 these struct were
|
||||
not part of virtio-net data structures, but were defined in those
|
||||
function. This macro does this definition, which is not necessary
|
||||
for subsequent versions. */
|
||||
#define COMPAT_DECL_SG struct scatterlist _compat_sg;
|
||||
|
||||
#else /* >= 2.6.35 */
|
||||
|
||||
#define DEV_NUM_RX_QUEUES(_netdev) (_netdev)->num_rx_queues
|
||||
#define COMPAT_DECL_SG
|
||||
|
||||
#endif /* >= 2.6.35 */
|
||||
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
|
||||
/* Before 2.6.35, the virtio interface was not exported with functions,
|
||||
but using virtqueue callbacks. */
|
||||
#define virtqueue_detach_unused_buf(_vq) \
|
||||
(_vq)->vq_ops->detach_unused_buf(_vq)
|
||||
#define virtqueue_get_buf(_vq, _lp) \
|
||||
(_vq)->vq_ops->get_buf(_vq, _lp)
|
||||
#define virtqueue_add_inbuf(_vq, _sg, _num, _tok, _gfp) \
|
||||
(_vq)->vq_ops->add_buf(_vq, _sg, 0, _num, _tok)
|
||||
#define virtqueue_add_outbuf(_vq, _sg, _num, _tok, _gfp) \
|
||||
(_vq)->vq_ops->add_buf(_vq, _sg, _num, 0, _tok)
|
||||
#define virtqueue_kick(_vq) \
|
||||
(_vq)->vq_ops->kick(_vq)
|
||||
#define virtqueue_enable_cb(_vq) \
|
||||
(_vq)->vq_ops->enable_cb(_vq)
|
||||
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
|
||||
/* Some simple renaming due to virtio interface changes. */
|
||||
#define virtqueue_add_inbuf(_vq, _sg, _num, _tok, _gfp) \
|
||||
virtqueue_add_buf_gfp(_vq, _sg, 0, _num, _tok, _gfp)
|
||||
#define virtqueue_add_outbuf(_vq, _sg, _num, _tok, _gfp) \
|
||||
virtqueue_add_buf_gfp(_vq, _sg, _num, 0, _tok, _gfp)
|
||||
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
|
||||
/* Some simple renaming due to virtio interface changes. */
|
||||
#define virtqueue_add_inbuf(_vq, _sg, _num, _tok, _gfp) \
|
||||
virtqueue_add_buf(_vq, _sg, 0, _num, _tok, _gfp)
|
||||
#define virtqueue_add_outbuf(_vq, _sg, _num, _tok, _gfp) \
|
||||
virtqueue_add_buf(_vq, _sg, _num, 0, _tok, _gfp)
|
||||
|
||||
#endif /* 3.3 <= VER < 3.10.0 */
|
||||
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0)
|
||||
/* The delayed optimization did not exists before version 3.0. */
|
||||
#define virtqueue_enable_cb_delayed(_vq) virtqueue_enable_cb(_vq)
|
||||
#endif /* < 3.0 */
|
||||
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)
|
||||
/* Not yet found a way to find out virtqueue length in these
|
||||
kernel series. Use the virtio default value. */
|
||||
#define virtqueue_get_vring_size(_vq) 256
|
||||
#endif /* < 3.2 */
|
||||
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
|
||||
/* Before 3.8.0 virtio did not have multiple queues, and therefore
|
||||
it did not have per-queue data structures. We then abstract the
|
||||
way data structure are accessed, ignoring the queue indexes. */
|
||||
#define DECR_NUM(_vi, _i) --(_vi)->num
|
||||
#define GET_RX_VQ(_vi, _i) (_vi)->rvq
|
||||
#define GET_TX_VQ(_vi, _i) (_vi)->svq
|
||||
#define VQ_FULL(_vq, _err) (_err > 0)
|
||||
|
||||
static void give_pages(struct SOFTC_T *vi, struct page *page);
|
||||
static struct page *get_a_page(struct SOFTC_T *vi, gfp_t gfp_mask);
|
||||
#define GIVE_PAGES(_vi, _i, _buf) give_pages(_vi, _buf)
|
||||
|
||||
/* This function did not exists, there was just the code. */
|
||||
static void free_receive_bufs(struct SOFTC_T *vi)
|
||||
{
|
||||
while (vi->pages)
|
||||
__free_pages(get_a_page(vi, GFP_KERNEL), 0);
|
||||
}
|
||||
|
||||
#else /* >= 3.8.0 */
|
||||
|
||||
static void give_pages(struct receive_queue *rq, struct page *page);
|
||||
#define GIVE_PAGES(_vi, _i, _buf) give_pages(&(_vi)->rq[_i], _buf)
|
||||
#define DECR_NUM(_vi, _i) --(_vi)->rq[_i].num
|
||||
#define GET_RX_VQ(_vi, _i) (_vi)->rq[_i].vq
|
||||
#define GET_TX_VQ(_vi, _i) (_vi)->sq[_i].vq
|
||||
#define VQ_FULL(_vq, _err) ((_vq)->num_free == 0)
|
||||
|
||||
#endif /* >= 3.8.0 */
|
||||
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
|
||||
/* Use the scatterlist struct defined in the current function
|
||||
(see above). */
|
||||
#define GET_RX_SG(_vi, _i) &_compat_sg
|
||||
#define GET_TX_SG(_vi, _i) &_compat_sg
|
||||
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
|
||||
/* Also here we create an abstraction because of multiqueue support
|
||||
(see above). */
|
||||
#define GET_RX_SG(_vi, _i) (_vi)->rx_sg
|
||||
#define GET_TX_SG(_vi, _i) (_vi)->tx_sg
|
||||
|
||||
#else /* >= 3.8.0 */
|
||||
|
||||
#define GET_RX_SG(_vi, _i) (_vi)->rq[_i].sg
|
||||
#define GET_TX_SG(_vi, _i) (_vi)->sq[_i].sg
|
||||
|
||||
#endif /* >= 3.8.0 */
|
||||
|
||||
|
||||
/* Free all the unused buffer in all the RX virtqueues.
|
||||
* This function is called when entering and exiting netmap mode.
|
||||
* In the former case, the unused buffers point to memory allocated by
|
||||
* the virtio-driver (e.g. sk_buffs). We need to free that
|
||||
* memory, otherwise we have leakage.
|
||||
* In the latter case, the unused buffers point to memory allocated by
|
||||
* netmap, and so we don't need to free anything.
|
||||
* We scan all the RX virtqueues, even those that have not been
|
||||
* activated (by 'ethtool --set-channels eth0 combined $N').
|
||||
*/
|
||||
static void virtio_netmap_free_rx_unused_bufs(struct SOFTC_T* vi, int onoff)
|
||||
{
|
||||
void *buf;
|
||||
int i, c;
|
||||
|
||||
for (i = 0; i < DEV_NUM_RX_QUEUES(vi->dev); i++) {
|
||||
struct virtqueue *vq = GET_RX_VQ(vi, i);
|
||||
|
||||
c = 0;
|
||||
while ((buf = virtqueue_detach_unused_buf(vq)) != NULL) {
|
||||
if (onoff) {
|
||||
if (vi->mergeable_rx_bufs || vi->big_packets)
|
||||
GIVE_PAGES(vi, i, buf);
|
||||
else
|
||||
dev_kfree_skb(buf);
|
||||
}
|
||||
DECR_NUM(vi, i);
|
||||
c++;
|
||||
}
|
||||
D("[%d] freed %d rx unused bufs on queue %d", onoff, c, i);
|
||||
}
|
||||
}
|
||||
|
||||
/* Register and unregister. */
|
||||
static int
|
||||
virtio_netmap_reg(struct netmap_adapter *na, int onoff)
|
||||
{
|
||||
struct ifnet *ifp = na->ifp;
|
||||
struct SOFTC_T *vi = netdev_priv(ifp);
|
||||
struct netmap_hw_adapter *hwna = (struct netmap_hw_adapter*)na;
|
||||
int error = 0;
|
||||
|
||||
if (na == NULL)
|
||||
return EINVAL;
|
||||
|
||||
/* It's important to deny the registration if the interface is
|
||||
not up, otherwise the virtnet_close() is not matched by a
|
||||
virtnet_open(), and so a napi_disable() is not matched by
|
||||
a napi_enable(), which results in a deadlock. */
|
||||
if (!netif_running(ifp))
|
||||
return EBUSY;
|
||||
|
||||
rtnl_lock();
|
||||
|
||||
/* Down the interface. This also disables napi. */
|
||||
virtnet_close(ifp);
|
||||
|
||||
if (onoff) {
|
||||
/* We have to drain the RX virtqueues, otherwise the
|
||||
* virtio_netmap_init_buffer() called by the subsequent
|
||||
* virtnet_open() cannot link the netmap buffers to the
|
||||
* virtio RX ring. */
|
||||
virtio_netmap_free_rx_unused_bufs(vi, onoff);
|
||||
/* Also free the pages allocated by the driver. */
|
||||
free_receive_bufs(vi);
|
||||
|
||||
/* enable netmap mode */
|
||||
ifp->if_capenable |= IFCAP_NETMAP;
|
||||
na->na_flags |= NAF_NATIVE_ON;
|
||||
na->if_transmit = (void *)ifp->netdev_ops;
|
||||
ifp->netdev_ops = &hwna->nm_ndo;
|
||||
} else {
|
||||
ifp->if_capenable &= ~IFCAP_NETMAP;
|
||||
na->na_flags &= ~NAF_NATIVE_ON;
|
||||
ifp->netdev_ops = (void *)na->if_transmit;
|
||||
|
||||
/* Drain the RX virtqueues, otherwise the driver will
|
||||
* interpret the netmap buffers currently linked to the
|
||||
* netmap ring as buffers allocated by the driver. This
|
||||
* would break the driver (and kernel panic/ooops). */
|
||||
virtio_netmap_free_rx_unused_bufs(vi, onoff);
|
||||
}
|
||||
|
||||
/* Up the interface. This also enables the napi. */
|
||||
virtnet_open(ifp);
|
||||
|
||||
rtnl_unlock();
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
||||
/* Reconcile kernel and user view of the transmit ring. */
|
||||
static int
|
||||
virtio_netmap_txsync(struct netmap_kring *kring, int flags)
|
||||
{
|
||||
struct netmap_adapter *na = kring->na;
|
||||
struct ifnet *ifp = na->ifp;
|
||||
struct netmap_ring *ring = kring->ring;
|
||||
u_int ring_nr = kring->ring_id;
|
||||
u_int nm_i; /* index into the netmap ring */
|
||||
u_int nic_i; /* index into the NIC ring */
|
||||
u_int n;
|
||||
u_int const lim = kring->nkr_num_slots - 1;
|
||||
u_int const head = kring->rhead;
|
||||
|
||||
/* device-specific */
|
||||
COMPAT_DECL_SG
|
||||
struct SOFTC_T *vi = netdev_priv(ifp);
|
||||
struct virtqueue *vq = GET_TX_VQ(vi, ring_nr);
|
||||
struct scatterlist *sg = GET_TX_SG(vi, ring_nr);
|
||||
struct netmap_adapter *token;
|
||||
|
||||
// XXX invert the order
|
||||
/* Free used slots. We only consider our own used buffers, recognized
|
||||
* by the token we passed to virtqueue_add_outbuf.
|
||||
*/
|
||||
n = 0;
|
||||
for (;;) {
|
||||
token = virtqueue_get_buf(vq, &nic_i); /* dummy 2nd arg */
|
||||
if (token == NULL)
|
||||
break;
|
||||
if (likely(token == na))
|
||||
n++;
|
||||
}
|
||||
kring->nr_hwtail += n;
|
||||
if (kring->nr_hwtail > lim)
|
||||
kring->nr_hwtail -= lim + 1;
|
||||
|
||||
/*
|
||||
* First part: process new packets to send.
|
||||
*/
|
||||
rmb();
|
||||
|
||||
if (!netif_carrier_ok(ifp)) {
|
||||
/* All the new slots are now unavailable. */
|
||||
goto out;
|
||||
}
|
||||
|
||||
nm_i = kring->nr_hwcur;
|
||||
if (nm_i != head) { /* we have new packets to send */
|
||||
nic_i = netmap_idx_k2n(kring, nm_i);
|
||||
for (n = 0; nm_i != head; n++) {
|
||||
struct netmap_slot *slot = &ring->slot[nm_i];
|
||||
u_int len = slot->len;
|
||||
void *addr = NMB(slot);
|
||||
int err;
|
||||
|
||||
NM_CHECK_ADDR_LEN(addr, len);
|
||||
|
||||
slot->flags &= ~(NS_REPORT | NS_BUF_CHANGED);
|
||||
/* Initialize the scatterlist, expose it to the hypervisor,
|
||||
* and kick the hypervisor (if necessary).
|
||||
*/
|
||||
sg_set_buf(sg, addr, len);
|
||||
err = virtqueue_add_outbuf(vq, sg, 1, na, GFP_ATOMIC);
|
||||
if (err < 0) {
|
||||
D("virtqueue_add_outbuf failed");
|
||||
break;
|
||||
}
|
||||
virtqueue_kick(vq);
|
||||
|
||||
nm_i = nm_next(nm_i, lim);
|
||||
nic_i = nm_next(nic_i, lim);
|
||||
}
|
||||
/* Update hwcur depending on where we stopped. */
|
||||
kring->nr_hwcur = nm_i; /* note we migth break early */
|
||||
|
||||
/* No more free TX slots? Ask the hypervisor for notifications,
|
||||
* possibly only when a considerable amount of work has been
|
||||
* done.
|
||||
*/
|
||||
if (nm_kr_txempty(kring))
|
||||
virtqueue_enable_cb_delayed(vq);
|
||||
}
|
||||
out:
|
||||
nm_txsync_finalize(kring);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Reconcile kernel and user view of the receive ring. */
|
||||
static int
|
||||
virtio_netmap_rxsync(struct netmap_kring *kring, int flags)
|
||||
{
|
||||
struct netmap_adapter *na = kring->na;
|
||||
struct ifnet *ifp = na->ifp;
|
||||
struct netmap_ring *ring = kring->ring;
|
||||
u_int ring_nr = kring->ring_id;
|
||||
u_int nm_i; /* index into the netmap ring */
|
||||
// u_int nic_i; /* index into the NIC ring */
|
||||
u_int n;
|
||||
u_int const lim = kring->nkr_num_slots - 1;
|
||||
u_int const head = nm_rxsync_prologue(kring);
|
||||
int force_update = (flags & NAF_FORCE_READ) || kring->nr_kflags & NKR_PENDINTR;
|
||||
|
||||
/* device-specific */
|
||||
COMPAT_DECL_SG
|
||||
struct SOFTC_T *vi = netdev_priv(ifp);
|
||||
struct virtqueue *vq = GET_RX_VQ(vi, ring_nr);
|
||||
struct scatterlist *sg = GET_RX_SG(vi, ring_nr);
|
||||
|
||||
/* XXX netif_carrier_ok ? */
|
||||
|
||||
if (head > lim)
|
||||
return netmap_ring_reinit(kring);
|
||||
|
||||
rmb();
|
||||
/*
|
||||
* First part: import newly received packets.
|
||||
* Only accept our
|
||||
* own buffers (matching the token). We should only get
|
||||
* matching buffers, because of virtio_netmap_free_rx_unused_bufs()
|
||||
* and virtio_netmap_init_buffers().
|
||||
*/
|
||||
if (netmap_no_pendintr || force_update) {
|
||||
uint16_t slot_flags = kring->nkr_slot_flags;
|
||||
struct netmap_adapter *token;
|
||||
|
||||
nm_i = kring->nr_hwtail;
|
||||
n = 0;
|
||||
for (;;) {
|
||||
int len;
|
||||
token = virtqueue_get_buf(vq, &len);
|
||||
if (token == NULL)
|
||||
break;
|
||||
if (likely(token == na)) {
|
||||
ring->slot[nm_i].len = len;
|
||||
ring->slot[nm_i].flags = slot_flags;
|
||||
nm_i = nm_next(nm_i, lim);
|
||||
n++;
|
||||
} else {
|
||||
D("This should not happen");
|
||||
}
|
||||
}
|
||||
kring->nr_hwtail = nm_i;
|
||||
kring->nr_kflags &= ~NKR_PENDINTR;
|
||||
}
|
||||
ND("[B] h %d c %d hwcur %d hwtail %d",
|
||||
ring->head, ring->cur, kring->nr_hwcur,
|
||||
kring->nr_hwtail);
|
||||
|
||||
/*
|
||||
* Second part: skip past packets that userspace has released.
|
||||
*/
|
||||
nm_i = kring->nr_hwcur; /* netmap ring index */
|
||||
if (nm_i != head) {
|
||||
for (n = 0; nm_i != head; n++) {
|
||||
struct netmap_slot *slot = &ring->slot[nm_i];
|
||||
void *addr = NMB(slot);
|
||||
int err;
|
||||
|
||||
if (addr == netmap_buffer_base) /* bad buf */
|
||||
return netmap_ring_reinit(kring);
|
||||
|
||||
slot->flags &= ~NS_BUF_CHANGED;
|
||||
|
||||
/* Initialize the scatterlist, expose it to the hypervisor,
|
||||
* and kick the hypervisor (if necessary).
|
||||
*/
|
||||
sg_set_buf(sg, addr, ring->nr_buf_size);
|
||||
err = virtqueue_add_inbuf(vq, sg, 1, na, GFP_ATOMIC);
|
||||
if (err < 0) {
|
||||
D("virtqueue_add_inbuf failed");
|
||||
return err;
|
||||
}
|
||||
virtqueue_kick(vq);
|
||||
nm_i = nm_next(nm_i, lim);
|
||||
}
|
||||
kring->nr_hwcur = head;
|
||||
}
|
||||
|
||||
/* We have finished processing used RX buffers, so we have to tell
|
||||
* the hypervisor to make a call when more used RX buffers will be
|
||||
* ready.
|
||||
*/
|
||||
virtqueue_enable_cb(vq);
|
||||
|
||||
/* tell userspace that there might be new packets. */
|
||||
nm_rxsync_finalize(kring);
|
||||
|
||||
ND("[C] h %d c %d t %d hwcur %d hwtail %d",
|
||||
ring->head, ring->cur, ring->tail,
|
||||
kring->nr_hwcur, kring->nr_hwtail);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Make RX virtqueues buffers pointing to netmap buffers. */
|
||||
static int virtio_netmap_init_buffers(struct SOFTC_T *vi)
|
||||
{
|
||||
struct ifnet *ifp = vi->dev;
|
||||
struct netmap_adapter* na = NA(ifp);
|
||||
unsigned int r;
|
||||
|
||||
if (!na || !(na->na_flags & NAF_NATIVE_ON)) {
|
||||
return 0;
|
||||
}
|
||||
for (r = 0; r < na->num_rx_rings; r++) {
|
||||
COMPAT_DECL_SG
|
||||
struct netmap_ring *ring = na->rx_rings[r].ring;
|
||||
struct virtqueue *vq = GET_RX_VQ(vi, r);
|
||||
struct scatterlist *sg = GET_RX_SG(vi, r);
|
||||
struct netmap_slot* slot;
|
||||
unsigned int i;
|
||||
int err = 0;
|
||||
|
||||
slot = netmap_reset(na, NR_RX, r, 0);
|
||||
if (!slot) {
|
||||
D("strange, null netmap ring %d", r);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Add up to na>-num_rx_desc-1 buffers to this RX virtqueue.
|
||||
* It's important to leave one virtqueue slot free, otherwise
|
||||
* we can run into ring->cur/ring->tail wraparounds.
|
||||
*/
|
||||
for (i = 0; i < na->num_rx_desc-1; i++) {
|
||||
void *addr;
|
||||
|
||||
slot = &ring->slot[i];
|
||||
addr = NMB(slot);
|
||||
sg_set_buf(sg, addr, ring->nr_buf_size);
|
||||
err = virtqueue_add_inbuf(vq, sg, 1, na, GFP_ATOMIC);
|
||||
if (err < 0) {
|
||||
D("virtqueue_add_inbuf failed");
|
||||
|
||||
return 0;
|
||||
}
|
||||
if (VQ_FULL(vq, err))
|
||||
break;
|
||||
}
|
||||
D("added %d inbufs on queue %d", i, r);
|
||||
virtqueue_kick(vq);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Update the virtio-net device configurations. Number of queues can
|
||||
* change dinamically, by 'ethtool --set-channels $IFNAME combined $N'.
|
||||
* This is actually the only way virtio-net can currently enable
|
||||
* the multiqueue mode.
|
||||
*/
|
||||
static int
|
||||
virtio_netmap_config(struct netmap_adapter *na, u_int *txr, u_int *txd,
|
||||
u_int *rxr, u_int *rxd)
|
||||
{
|
||||
struct ifnet *ifp = na->ifp;
|
||||
struct SOFTC_T *vi = netdev_priv(ifp);
|
||||
|
||||
*txr = ifp->real_num_tx_queues;
|
||||
*txd = virtqueue_get_vring_size(GET_TX_VQ(vi, 0));
|
||||
*rxr = 1;
|
||||
*rxd = virtqueue_get_vring_size(GET_RX_VQ(vi, 0));
|
||||
D("virtio config txq=%d, txd=%d rxq=%d, rxd=%d",
|
||||
*txr, *txd, *rxr, *rxd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
virtio_netmap_attach(struct SOFTC_T *vi)
|
||||
{
|
||||
struct netmap_adapter na;
|
||||
|
||||
bzero(&na, sizeof(na));
|
||||
|
||||
na.ifp = vi->dev;
|
||||
na.num_tx_desc = virtqueue_get_vring_size(GET_TX_VQ(vi, 0));
|
||||
na.num_rx_desc = virtqueue_get_vring_size(GET_RX_VQ(vi, 0));
|
||||
na.nm_register = virtio_netmap_reg;
|
||||
na.nm_txsync = virtio_netmap_txsync;
|
||||
na.nm_rxsync = virtio_netmap_rxsync;
|
||||
na.nm_config = virtio_netmap_config;
|
||||
na.num_tx_rings = na.num_rx_rings = 1;
|
||||
netmap_attach(&na);
|
||||
|
||||
D("virtio attached txq=%d, txd=%d rxq=%d, rxd=%d",
|
||||
na.num_tx_rings, na.num_tx_desc,
|
||||
na.num_tx_rings, na.num_rx_desc);
|
||||
}
|
||||
/* end of file */
|
145
netmap/LINUX/wip-patches/diff--mellanox--30300--30800
Normal file
145
netmap/LINUX/wip-patches/diff--mellanox--30300--30800
Normal file
@ -0,0 +1,145 @@
|
||||
diff -urp --exclude '*.o' --exclude '*.cmd' --exclude '*mod.c' drivers/net/ethernet/mellanox/mlx4/en_netdev.c ./mellanox/mlx4/en_netdev.c
|
||||
--- drivers/net/ethernet/mellanox/mlx4/en_netdev.c 2012-09-11 20:50:55.982624673 -0700
|
||||
+++ ./mellanox/mlx4/en_netdev.c 2012-09-27 00:05:22.703523430 -0700
|
||||
@@ -48,6 +48,39 @@
|
||||
#include "mlx4_en.h"
|
||||
#include "en_port.h"
|
||||
|
||||
+#if defined(CONFIG_NETMAP) || defined(CONFIG_NETMAP_MODULE)
|
||||
+/*
|
||||
+ * This driver is split in multiple small files.
|
||||
+ * The main device descriptor has type struct mlx4_en_priv *priv;
|
||||
+ * and we attach to the device in mlx4_en_init_netdev()
|
||||
+ * (do port numbers start from 1 ?)
|
||||
+ *
|
||||
+ * The reconfig routine is in mlx4_en_start_port() (also here)
|
||||
+ * which is called on a mlx4_en_restart() (watchdog), open and set-mtu.
|
||||
+ *
|
||||
+ * priv->num_frags ??
|
||||
+ * DS_SIZE ??
|
||||
+ * apparently each rx desc is followed by frag.descriptors
|
||||
+ * and the rx desc is rounded up to a power of 2.
|
||||
+ *
|
||||
+ * Receive code is in en_rx.c
|
||||
+ * priv->rx_ring_num number of rx rings
|
||||
+ * rxr = prov->rx_ring[ring_ind] rx ring descriptor
|
||||
+ * rxr->size number of slots
|
||||
+ * rxr->prod producer
|
||||
+ * probably written into a mmio reg at *rxr->wqres.db.db
|
||||
+ * trimmed to 16 bits.
|
||||
+ *
|
||||
+ * Rx init routine:
|
||||
+ * mlx4_en_activate_rx_rings()
|
||||
+ * mlx4_en_init_rx_desc()
|
||||
+ * Transmit code is in en_tx.c
|
||||
+ */
|
||||
+
|
||||
+#define NETMAP_MLX4_MAIN
|
||||
+#include <mlx4_netmap_linux.h> /* extern stuff */
|
||||
+#endif /* CONFIG_NETMAP */
|
||||
+
|
||||
int mlx4_en_setup_tc(struct net_device *dev, u8 up)
|
||||
{
|
||||
if (up != MLX4_EN_NUM_UP)
|
||||
@@ -1042,6 +1075,9 @@ int mlx4_en_start_port(struct net_device
|
||||
/* Set initial ownership of all Tx TXBBs to SW (1) */
|
||||
for (j = 0; j < tx_ring->buf_size; j += STAMP_STRIDE)
|
||||
*((u32 *) (tx_ring->buf + j)) = 0xffffffff;
|
||||
+#ifdef DEV_NETMAP
|
||||
+ mlx4_netmap_tx_config(priv, i);
|
||||
+#endif /* DEV_NETMAP */
|
||||
++tx_index;
|
||||
}
|
||||
|
||||
@@ -1639,6 +1675,9 @@ int mlx4_en_init_netdev(struct mlx4_en_d
|
||||
en_warn(priv, "Using %d RX rings\n", prof->rx_ring_num);
|
||||
|
||||
queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY);
|
||||
+#ifdef DEV_NETMAP
|
||||
+ mlx4_netmap_attach(priv);
|
||||
+#endif /* DEV_NETMAP */
|
||||
return 0;
|
||||
|
||||
out:
|
||||
--- drivers/net/ethernet/mellanox/mlx4/en_rx.c 2012-09-11 20:50:55.982624673 -0700
|
||||
+++ ./mellanox/mlx4/en_rx.c 2012-09-27 00:13:16.099550954 -0700
|
||||
@@ -41,6 +41,9 @@
|
||||
|
||||
#include "mlx4_en.h"
|
||||
|
||||
+#if defined(CONFIG_NETMAP) || defined(CONFIG_NETMAP_MODULE)
|
||||
+#include <mlx4_netmap_linux.h>
|
||||
+#endif /* !DEV_NETMAP */
|
||||
|
||||
static int mlx4_en_alloc_frag(struct mlx4_en_priv *priv,
|
||||
struct mlx4_en_rx_desc *rx_desc,
|
||||
@@ -365,9 +368,16 @@ int mlx4_en_activate_rx_rings(struct mlx
|
||||
ring = &priv->rx_ring[ring_ind];
|
||||
|
||||
ring->size_mask = ring->actual_size - 1;
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (priv->dev->if_capenable & IFCAP_NETMAP) {
|
||||
+ int saved_cons = ring->cons;
|
||||
+ mlx4_en_free_rx_buf(priv, ring);
|
||||
+ ring->cons = saved_cons;
|
||||
+ mlx4_netmap_rx_config(priv, ring_ind);
|
||||
+ }
|
||||
+#endif /* DEV_NETMAP */
|
||||
mlx4_en_update_rx_prod_db(ring);
|
||||
}
|
||||
-
|
||||
return 0;
|
||||
|
||||
err_buffers:
|
||||
@@ -402,6 +412,11 @@ void mlx4_en_destroy_rx_ring(struct mlx4
|
||||
void mlx4_en_deactivate_rx_ring(struct mlx4_en_priv *priv,
|
||||
struct mlx4_en_rx_ring *ring)
|
||||
{
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (priv->dev->if_capenable & IFCAP_NETMAP)
|
||||
+ ND("netmap mode, rx buf already freed");
|
||||
+ else
|
||||
+#endif /* DEV_NETMAP */
|
||||
mlx4_en_free_rx_buf(priv, ring);
|
||||
if (ring->stride <= TXBB_SIZE)
|
||||
ring->buf -= TXBB_SIZE;
|
||||
@@ -718,6 +739,11 @@ int mlx4_en_poll_rx_cq(struct napi_struc
|
||||
struct mlx4_en_priv *priv = netdev_priv(dev);
|
||||
int done;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (netmap_rx_irq(cq->dev, cq->ring, &done)) {
|
||||
+ ND("rx_irq %d for netmap, budget %d done %d", cq->ring, budget, done);
|
||||
+ } else
|
||||
+#endif /* DEV_NETMAP */
|
||||
done = mlx4_en_process_rx_cq(dev, cq, budget);
|
||||
|
||||
/* If we used up all the quota - we're probably not done yet... */
|
||||
--- drivers/net/ethernet/mellanox/mlx4/en_tx.c 2012-09-11 20:50:55.982624673 -0700
|
||||
+++ ./mellanox/mlx4/en_tx.c 2012-09-27 00:05:22.713523348 -0700
|
||||
@@ -55,6 +55,10 @@ MODULE_PARM_DESC(inline_thold, "threshol
|
||||
|
||||
static u32 hashrnd __read_mostly;
|
||||
|
||||
+#if defined(CONFIG_NETMAP) || defined(CONFIG_NETMAP_MODULE)
|
||||
+#include <mlx4_netmap_linux.h> /* extern stuff */
|
||||
+#endif /* CONFIG_NETMAP */
|
||||
+
|
||||
int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv,
|
||||
struct mlx4_en_tx_ring *ring, u32 size,
|
||||
u16 stride)
|
||||
@@ -396,6 +400,13 @@ void mlx4_en_tx_irq(struct mlx4_cq *mcq)
|
||||
|
||||
if (!spin_trylock(&ring->comp_lock))
|
||||
return;
|
||||
+#ifdef DEV_NETMAP
|
||||
+ /* XXX should be integrated with appropriate lock_wrapper manner? */
|
||||
+ if (netmap_tx_irq(cq->dev, cq->ring)) {
|
||||
+ ND(5, "wakeup queue %d", cq->ring);
|
||||
+ spin_unlock(&ring->comp_lock);
|
||||
+ return;
|
||||
+ }
|
||||
+#endif /* DEV_NETMAP */
|
||||
mlx4_en_process_tx_cq(cq->dev, cq);
|
||||
mod_timer(&cq->timer, jiffies + 1);
|
||||
spin_unlock(&ring->comp_lock);
|
163
netmap/LINUX/wip-patches/diff--mlx4--20630--30200
Normal file
163
netmap/LINUX/wip-patches/diff--mlx4--20630--30200
Normal file
@ -0,0 +1,163 @@
|
||||
diff -urp --exclude '*.o' --exclude '*.cmd' --exclude '*mod.c' drivers/net/ethernet/mellanox/mlx4/en_netdev.c ./mellanox/mlx4/en_netdev.c
|
||||
--- drivers/net/ethernet/mellanox/mlx4/en_netdev.c 2012-09-11 20:50:55.982624673 -0700
|
||||
+++ ./mlx4/en_netdev.c 2012-09-27 00:05:22.703523430 -0700
|
||||
@@ -48,6 +48,39 @@
|
||||
#include "mlx4_en.h"
|
||||
#include "en_port.h"
|
||||
|
||||
+#if defined(CONFIG_NETMAP) || defined(CONFIG_NETMAP_MODULE)
|
||||
+/*
|
||||
+ * This driver is split in multiple small files.
|
||||
+ * The main device descriptor has type struct mlx4_en_priv *priv;
|
||||
+ * and we attach to the device in mlx4_en_init_netdev()
|
||||
+ * (do port numbers start from 1 ?)
|
||||
+ *
|
||||
+ * The reconfig routine is in mlx4_en_start_port() (also here)
|
||||
+ * which is called on a mlx4_en_restart() (watchdog), open and set-mtu.
|
||||
+ *
|
||||
+ * priv->num_frags ??
|
||||
+ * DS_SIZE ??
|
||||
+ * apparently each rx desc is followed by frag.descriptors
|
||||
+ * and the rx desc is rounded up to a power of 2.
|
||||
+ *
|
||||
+ * Receive code is in en_rx.c
|
||||
+ * priv->rx_ring_num number of rx rings
|
||||
+ * rxr = prov->rx_ring[ring_ind] rx ring descriptor
|
||||
+ * rxr->size number of slots
|
||||
+ * rxr->prod producer
|
||||
+ * probably written into a mmio reg at *rxr->wqres.db.db
|
||||
+ * trimmed to 16 bits.
|
||||
+ *
|
||||
+ * Rx init routine:
|
||||
+ * mlx4_en_activate_rx_rings()
|
||||
+ * mlx4_en_init_rx_desc()
|
||||
+ * Transmit code is in en_tx.c
|
||||
+ */
|
||||
+
|
||||
+#define NETMAP_MLX4_MAIN
|
||||
+#include <mlx4_netmap_linux.h> /* extern stuff */
|
||||
+#endif /* CONFIG_NETMAP */
|
||||
+
|
||||
int mlx4_en_setup_tc(struct net_device *dev, u8 up)
|
||||
{
|
||||
if (up != MLX4_EN_NUM_UP)
|
||||
@@ -1042,6 +1075,9 @@ int mlx4_en_start_port(struct net_device
|
||||
/* Set initial ownership of all Tx TXBBs to SW (1) */
|
||||
for (j = 0; j < tx_ring->buf_size; j += STAMP_STRIDE)
|
||||
*((u32 *) (tx_ring->buf + j)) = 0xffffffff;
|
||||
+#ifdef DEV_NETMAP
|
||||
+ mlx4_netmap_tx_config(priv, i);
|
||||
+#endif /* DEV_NETMAP */
|
||||
++tx_index;
|
||||
}
|
||||
|
||||
@@ -1639,6 +1675,9 @@ int mlx4_en_init_netdev(struct mlx4_en_d
|
||||
en_warn(priv, "Using %d RX rings\n", prof->rx_ring_num);
|
||||
|
||||
queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY);
|
||||
+#ifdef DEV_NETMAP
|
||||
+ mlx4_netmap_attach(priv);
|
||||
+#endif /* DEV_NETMAP */
|
||||
return 0;
|
||||
|
||||
out:
|
||||
--- drivers/net/ethernet/mellanox/mlx4/en_rx.c 2012-09-11 20:50:55.982624673 -0700
|
||||
+++ ./mlx4/en_rx.c 2012-09-27 00:13:16.099550954 -0700
|
||||
@@ -41,6 +41,9 @@
|
||||
|
||||
#include "mlx4_en.h"
|
||||
|
||||
+#if defined(CONFIG_NETMAP) || defined(CONFIG_NETMAP_MODULE)
|
||||
+#include <mlx4_netmap_linux.h>
|
||||
+#endif /* !DEV_NETMAP */
|
||||
|
||||
static int mlx4_en_alloc_frag(struct mlx4_en_priv *priv,
|
||||
struct mlx4_en_rx_desc *rx_desc,
|
||||
@@ -365,9 +368,16 @@ int mlx4_en_activate_rx_rings(struct mlx
|
||||
ring = &priv->rx_ring[ring_ind];
|
||||
|
||||
ring->size_mask = ring->actual_size - 1;
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (priv->dev->if_capenable & IFCAP_NETMAP) {
|
||||
+ int saved_cons = ring->cons;
|
||||
+ mlx4_en_free_rx_buf(priv, ring);
|
||||
+ ring->cons = saved_cons;
|
||||
+ mlx4_netmap_rx_config(priv, ring_ind);
|
||||
+ }
|
||||
+#endif /* DEV_NETMAP */
|
||||
mlx4_en_update_rx_prod_db(ring);
|
||||
}
|
||||
-
|
||||
return 0;
|
||||
|
||||
err_buffers:
|
||||
@@ -402,6 +412,11 @@ void mlx4_en_destroy_rx_ring(struct mlx4
|
||||
void mlx4_en_deactivate_rx_ring(struct mlx4_en_priv *priv,
|
||||
struct mlx4_en_rx_ring *ring)
|
||||
{
|
||||
+#ifdef DEV_NETMAP
|
||||
+ if (priv->dev->if_capenable & IFCAP_NETMAP)
|
||||
+ ND("netmap mode, rx buf already freed");
|
||||
+ else
|
||||
+#endif /* DEV_NETMAP */
|
||||
mlx4_en_free_rx_buf(priv, ring);
|
||||
if (ring->stride <= TXBB_SIZE)
|
||||
ring->buf -= TXBB_SIZE;
|
||||
@@ -692,6 +707,12 @@ out:
|
||||
wmb(); /* ensure HW sees CQ consumer before we post new buffers */
|
||||
ring->cons = mcq->cons_index;
|
||||
ring->prod += polled; /* Polled descriptors were realocated in place */
|
||||
+
|
||||
+ ND(5, "set_ci %d 0x%p val %d prod_db 0x%p val %d",
|
||||
+ cq->ring,
|
||||
+ mcq->set_ci_db, mcq->cons_index & 0xffffff,
|
||||
+ ring->wqres.db.db, ring->prod & 0xffff);
|
||||
+
|
||||
mlx4_en_update_rx_prod_db(ring);
|
||||
ring->csum_ok += csum_ok;
|
||||
ring->csum_none += csum_none;
|
||||
@@ -718,6 +739,13 @@ int mlx4_en_poll_rx_cq(struct napi_struc
|
||||
struct mlx4_en_priv *priv = netdev_priv(dev);
|
||||
int done;
|
||||
|
||||
+#ifdef DEV_NETMAP
|
||||
+ static int cnt = 0;
|
||||
+ ND(5,"XXXXXX-------XXXXXXXXXXX-------- poll-rx-cq %d count %d", (int)cq->ring, cnt++);
|
||||
+ if (netmap_rx_irq(cq->dev, cq->ring, &done)) {
|
||||
+ ND("rx_irq %d for netmap, budget %d done %d", cq->ring, budget, done);
|
||||
+ } else
|
||||
+#endif /* DEV_NETMAP */
|
||||
done = mlx4_en_process_rx_cq(dev, cq, budget);
|
||||
|
||||
/* If we used up all the quota - we're probably not done yet... */
|
||||
--- drivers/net/ethernet/mellanox/mlx4/en_tx.c 2012-09-11 20:50:55.982624673 -0700
|
||||
+++ ./mlx4/en_tx.c 2012-09-27 00:05:22.713523348 -0700
|
||||
@@ -55,6 +55,10 @@ MODULE_PARM_DESC(inline_thold, "threshol
|
||||
|
||||
static u32 hashrnd __read_mostly;
|
||||
|
||||
+#if defined(CONFIG_NETMAP) || defined(CONFIG_NETMAP_MODULE)
|
||||
+#include <mlx4_netmap_linux.h> /* extern stuff */
|
||||
+#endif /* CONFIG_NETMAP */
|
||||
+
|
||||
int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv,
|
||||
struct mlx4_en_tx_ring *ring, u32 size,
|
||||
u16 stride)
|
||||
@@ -396,6 +400,17 @@ void mlx4_en_tx_irq(struct mlx4_cq *mcq)
|
||||
|
||||
if (!spin_trylock(&ring->comp_lock))
|
||||
return;
|
||||
+#ifdef DEV_NETMAP // XXX unlock and return should be in the 'if' branch
|
||||
+ static int cnt = 0;
|
||||
+ ND(5,"XXXXXX-------XXXXXXXXXXX-------- tx-irq %d count %d", (int)cq->ring, cnt++);
|
||||
+ if (netmap_tx_irq(cq->dev, cq->ring)) {
|
||||
+ ND(5, "wakeup queue %d", cq->ring);
|
||||
+ } else {
|
||||
+ RD(5, "XXXXXXXXX tx_irq %d unexpected, ignoring", cq->ring);
|
||||
+ }
|
||||
+ spin_unlock(&ring->comp_lock);
|
||||
+ return;
|
||||
+#endif /* DEV_NETMAP */
|
||||
mlx4_en_process_tx_cq(cq->dev, cq);
|
||||
mod_timer(&cq->timer, jiffies + 1);
|
||||
spin_unlock(&ring->comp_lock);
|
Reference in New Issue
Block a user