Add netmap support for ixgbe SRIOV VFs (that is, to if_ixv).

Differential Revision: https://reviews.freebsd.org/D2923
Reviewed by: erj, gnn
Approved by: jmallett (mentor)
Sponsored by: Norse Corp, Inc.
This commit is contained in:
Patrick Kelsey 2015-07-15 01:02:01 +00:00
parent fd3e9bafbd
commit 8aa7fdbd78
5 changed files with 77 additions and 16 deletions

View File

@ -362,7 +362,7 @@ device xenpci # Xen HVM Hypervisor services driver
device vmx # VMware VMXNET3 Ethernet
# Netmap provides direct access to TX/RX rings on supported NICs
device netmap # netmap(4) support
# device netmap # netmap(4) support
# The crypto framework is required by IPSEC
device crypto # Required by IPSEC

View File

@ -442,6 +442,11 @@ ixgbe_attach(device_t dev)
adapter->dev = adapter->osdep.dev = dev;
hw = &adapter->hw;
#ifdef DEV_NETMAP
adapter->init_locked = ixgbe_init_locked;
adapter->stop_locked = ixgbe_stop;
#endif
/* Core Lock Init*/
IXGBE_CORE_LOCK_INIT(adapter, device_get_nameunit(dev));

View File

@ -124,6 +124,18 @@ static void ixv_msix_mbx(void *);
static void ixv_handle_que(void *, int);
static void ixv_handle_mbx(void *, int);
#ifdef DEV_NETMAP
/*
* This is defined in <dev/netmap/ixgbe_netmap.h>, which is included by
* if_ix.c.
*/
extern void ixgbe_netmap_attach(struct adapter *adapter);
#include <net/netmap.h>
#include <sys/selinfo.h>
#include <dev/netmap/netmap_kern.h>
#endif /* DEV_NETMAP */
/*********************************************************************
* FreeBSD Device Interface Entry Points
*********************************************************************/
@ -145,6 +157,9 @@ devclass_t ixv_devclass;
DRIVER_MODULE(ixv, pci, ixv_driver, ixv_devclass, 0, 0);
MODULE_DEPEND(ixv, pci, 1, 1, 1);
MODULE_DEPEND(ixv, ether, 1, 1, 1);
#ifdef DEV_NETMAP
MODULE_DEPEND(ix, netmap, 1, 1, 1);
#endif /* DEV_NETMAP */
/* XXX depend on 'ix' ? */
/*
@ -278,6 +293,11 @@ ixv_attach(device_t dev)
adapter->dev = adapter->osdep.dev = dev;
hw = &adapter->hw;
#ifdef DEV_NETMAP
adapter->init_locked = ixv_init_locked;
adapter->stop_locked = ixv_stop;
#endif
/* Core Lock Init*/
IXGBE_CORE_LOCK_INIT(adapter, device_get_nameunit(dev));
@ -381,6 +401,9 @@ ixv_attach(device_t dev)
adapter->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig,
ixv_unregister_vlan, adapter, EVENTHANDLER_PRI_FIRST);
#ifdef DEV_NETMAP
ixgbe_netmap_attach(adapter);
#endif /* DEV_NETMAP */
INIT_DEBUGOUT("ixv_attach: end");
return (0);
@ -444,6 +467,9 @@ ixv_detach(device_t dev)
ether_ifdetach(adapter->ifp);
callout_drain(&adapter->timer);
#ifdef DEV_NETMAP
netmap_detach(adapter->ifp);
#endif /* DEV_NETMAP */
ixv_free_pci_resources(adapter);
bus_generic_detach(dev);
if_free(adapter->ifp);
@ -1685,8 +1711,33 @@ ixv_initialize_receive_units(struct adapter *adapter)
wmb();
/* Set the Tail Pointer */
IXGBE_WRITE_REG(hw, IXGBE_VFRDT(rxr->me),
adapter->num_rx_desc - 1);
#ifdef DEV_NETMAP
/*
* 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.
*/
if (ifp->if_capenable & IFCAP_NETMAP) {
struct netmap_adapter *na = NA(adapter->ifp);
struct netmap_kring *kring = &na->rx_rings[i];
int t = na->num_rx_desc - 1 - nm_kr_rxspace(kring);
IXGBE_WRITE_REG(hw, IXGBE_VFRDT(rxr->me), t);
} else
#endif /* DEV_NETMAP */
IXGBE_WRITE_REG(hw, IXGBE_VFRDT(rxr->me),
adapter->num_rx_desc - 1);
}
rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM);

View File

@ -555,6 +555,10 @@ struct adapter {
#ifdef PCI_IOV
struct ixgbe_vf *vfs;
#endif
#ifdef DEV_NETMAP
void (*init_locked)(struct adapter *);
void (*stop_locked)(void *);
#endif
/* Misc stats maintained by the driver */
unsigned long dropped_pkts;

View File

@ -26,7 +26,7 @@
/*
* $FreeBSD$
*
* netmap support for: ixgbe
* netmap support for: ixgbe (both ix and ixv)
*
* This file is meant to be a reference on how to implement
* netmap support for a network driver.
@ -48,6 +48,7 @@
*/
#include <dev/netmap/netmap_kern.h>
void ixgbe_netmap_attach(struct adapter *adapter);
/*
* device-specific sysctl variables:
@ -120,20 +121,19 @@ ixgbe_netmap_reg(struct netmap_adapter *na, int onoff)
struct adapter *adapter = ifp->if_softc;
IXGBE_CORE_LOCK(adapter);
ixgbe_disable_intr(adapter); // XXX maybe ixgbe_stop ?
adapter->stop_locked(adapter);
/* Tell the stack that the interface is no longer active */
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
set_crcstrip(&adapter->hw, onoff);
if (!IXGBE_IS_VF(adapter))
set_crcstrip(&adapter->hw, onoff);
/* enable or disable flags and callbacks in na and ifp */
if (onoff) {
nm_set_native_flags(na);
} else {
nm_clear_native_flags(na);
}
ixgbe_init_locked(adapter); /* also enables intr */
set_crcstrip(&adapter->hw, onoff); // XXX why twice ?
adapter->init_locked(adapter); /* also enables intr */
if (!IXGBE_IS_VF(adapter))
set_crcstrip(&adapter->hw, onoff); // XXX why twice ?
IXGBE_CORE_UNLOCK(adapter);
return (ifp->if_drv_flags & IFF_DRV_RUNNING ? 0 : 1);
}
@ -266,7 +266,7 @@ ixgbe_netmap_txsync(struct netmap_kring *kring, int flags)
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
/* (re)start the tx unit up to slot nic_i (excluded) */
IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDT(txr->me), nic_i);
IXGBE_WRITE_REG(&adapter->hw, txr->tail, nic_i);
}
/*
@ -310,7 +310,8 @@ ixgbe_netmap_txsync(struct netmap_kring *kring, int flags)
* REPORT_STATUS in a few slots so TDH is the only
* good way.
*/
nic_i = IXGBE_READ_REG(&adapter->hw, IXGBE_TDH(kring->ring_id));
nic_i = IXGBE_READ_REG(&adapter->hw, IXGBE_IS_VF(adapter) ?
IXGBE_VFTDH(kring->ring_id) : IXGBE_TDH(kring->ring_id));
if (nic_i >= kring->nkr_num_slots) { /* XXX can it happen ? */
D("TDH wrap %d", nic_i);
nic_i -= kring->nkr_num_slots;
@ -379,7 +380,7 @@ ixgbe_netmap_rxsync(struct netmap_kring *kring, int flags)
* rxr->next_to_check is set to 0 on a ring reinit
*/
if (netmap_no_pendintr || force_update) {
int crclen = ix_crcstrip ? 0 : 4;
int crclen = (ix_crcstrip || IXGBE_IS_VF(adapter) ) ? 0 : 4;
uint16_t slot_flags = kring->nkr_slot_flags;
nic_i = rxr->next_to_check; // or also k2n(kring->nr_hwtail)
@ -453,7 +454,7 @@ ixgbe_netmap_rxsync(struct netmap_kring *kring, int flags)
* so move nic_i back by one unit
*/
nic_i = nm_prev(nic_i, lim);
IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDT(rxr->me), nic_i);
IXGBE_WRITE_REG(&adapter->hw, rxr->tail, nic_i);
}
return 0;
@ -470,7 +471,7 @@ ixgbe_netmap_rxsync(struct netmap_kring *kring, int flags)
* netmap mode will be disabled and the driver will only
* operate in standard mode.
*/
static void
void
ixgbe_netmap_attach(struct adapter *adapter)
{
struct netmap_adapter na;