Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/netmap/ixgbe_netmap.h
Show All 20 Lines | |||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | * 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 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||||
* SUCH DAMAGE. | * SUCH DAMAGE. | ||||
*/ | */ | ||||
/* | /* | ||||
* $FreeBSD$ | * $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 | * This file is meant to be a reference on how to implement | ||||
* netmap support for a network driver. | * netmap support for a network driver. | ||||
* This file contains code but only static or inline functions used | * This file contains code but only static or inline functions used | ||||
* by a single driver. To avoid replication of code we just #include | * by a single driver. To avoid replication of code we just #include | ||||
* it near the beginning of the standard driver. | * it near the beginning of the standard driver. | ||||
*/ | */ | ||||
#include <net/netmap.h> | #include <net/netmap.h> | ||||
#include <sys/selinfo.h> | #include <sys/selinfo.h> | ||||
/* | /* | ||||
* Some drivers may need the following headers. Others | * Some drivers may need the following headers. Others | ||||
* already include them by default | * already include them by default | ||||
#include <vm/vm.h> | #include <vm/vm.h> | ||||
#include <vm/pmap.h> | #include <vm/pmap.h> | ||||
*/ | */ | ||||
#include <dev/netmap/netmap_kern.h> | #include <dev/netmap/netmap_kern.h> | ||||
void ixgbe_netmap_attach(struct adapter *adapter); | |||||
/* | /* | ||||
* device-specific sysctl variables: | * device-specific sysctl variables: | ||||
* | * | ||||
* ix_crcstrip: 0: keep CRC in rx frames (default), 1: strip it. | * ix_crcstrip: 0: keep CRC in rx frames (default), 1: strip it. | ||||
* During regular operations the CRC is stripped, but on some | * During regular operations the CRC is stripped, but on some | ||||
* hardware reception of frames not multiple of 64 is slower, | * hardware reception of frames not multiple of 64 is slower, | ||||
* so using crcstrip=0 helps in benchmarks. | * so using crcstrip=0 helps in benchmarks. | ||||
▲ Show 20 Lines • Show All 58 Lines • ▼ Show 20 Lines | |||||
ixgbe_netmap_reg(struct netmap_adapter *na, int onoff) | ixgbe_netmap_reg(struct netmap_adapter *na, int onoff) | ||||
{ | { | ||||
struct ifnet *ifp = na->ifp; | struct ifnet *ifp = na->ifp; | ||||
struct adapter *adapter = ifp->if_softc; | struct adapter *adapter = ifp->if_softc; | ||||
IXGBE_CORE_LOCK(adapter); | IXGBE_CORE_LOCK(adapter); | ||||
ixgbe_disable_intr(adapter); // XXX maybe ixgbe_stop ? | ixgbe_disable_intr(adapter); // XXX maybe ixgbe_stop ? | ||||
/* Tell the stack that the interface is no longer active */ | if (!IXGBE_IS_VF(adapter)) | ||||
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); | |||||
set_crcstrip(&adapter->hw, onoff); | set_crcstrip(&adapter->hw, onoff); | ||||
/* enable or disable flags and callbacks in na and ifp */ | /* enable or disable flags and callbacks in na and ifp */ | ||||
if (onoff) { | if (onoff) { | ||||
nm_set_native_flags(na); | nm_set_native_flags(na); | ||||
} else { | } else { | ||||
nm_clear_native_flags(na); | nm_clear_native_flags(na); | ||||
} | } | ||||
ixgbe_init_locked(adapter); /* also enables intr */ | ixgbe_init_locked(adapter); /* also enables intr */ | ||||
if (!IXGBE_IS_VF(adapter)) | |||||
set_crcstrip(&adapter->hw, onoff); // XXX why twice ? | set_crcstrip(&adapter->hw, onoff); // XXX why twice ? | ||||
IXGBE_CORE_UNLOCK(adapter); | IXGBE_CORE_UNLOCK(adapter); | ||||
return (ifp->if_drv_flags & IFF_DRV_RUNNING ? 0 : 1); | return (ifp->if_drv_flags & IFF_DRV_RUNNING ? 0 : 1); | ||||
} | } | ||||
/* | /* | ||||
* Reconcile kernel and user view of the transmit ring. | * Reconcile kernel and user view of the transmit ring. | ||||
* | * | ||||
▲ Show 20 Lines • Show All 116 Lines • ▼ Show 20 Lines | if (nm_i != head) { /* we have new packets to send */ | ||||
} | } | ||||
kring->nr_hwcur = head; | kring->nr_hwcur = head; | ||||
/* synchronize the NIC ring */ | /* synchronize the NIC ring */ | ||||
bus_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map, | bus_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map, | ||||
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); | BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); | ||||
/* (re)start the tx unit up to slot nic_i (excluded) */ | /* (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); | ||||
} | } | ||||
/* | /* | ||||
* Second part: reclaim buffers for completed transmissions. | * Second part: reclaim buffers for completed transmissions. | ||||
* Because this is expensive (we read a NIC register etc.) | * Because this is expensive (we read a NIC register etc.) | ||||
* we only do it in specific cases (see below). | * we only do it in specific cases (see below). | ||||
*/ | */ | ||||
if (flags & NAF_FORCE_RECLAIM) { | if (flags & NAF_FORCE_RECLAIM) { | ||||
Show All 27 Lines | if (reclaim_tx) { | ||||
* We (re)use the driver's txr->next_to_clean to keep | * We (re)use the driver's txr->next_to_clean to keep | ||||
* track of the most recently completed transmission. | * track of the most recently completed transmission. | ||||
* | * | ||||
* The datasheet discourages the use of TDH to find | * The datasheet discourages the use of TDH to find | ||||
* out the number of sent packets, but we only set | * out the number of sent packets, but we only set | ||||
* REPORT_STATUS in a few slots so TDH is the only | * REPORT_STATUS in a few slots so TDH is the only | ||||
* good way. | * 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 ? */ | if (nic_i >= kring->nkr_num_slots) { /* XXX can it happen ? */ | ||||
D("TDH wrap %d", nic_i); | D("TDH wrap %d", nic_i); | ||||
nic_i -= kring->nkr_num_slots; | nic_i -= kring->nkr_num_slots; | ||||
} | } | ||||
if (nic_i != txr->next_to_clean) { | if (nic_i != txr->next_to_clean) { | ||||
/* some tx completed, increment avail */ | /* some tx completed, increment avail */ | ||||
txr->next_to_clean = nic_i; | txr->next_to_clean = nic_i; | ||||
kring->nr_hwtail = nm_prev(netmap_idx_n2k(kring, nic_i), lim); | kring->nr_hwtail = nm_prev(netmap_idx_n2k(kring, nic_i), lim); | ||||
▲ Show 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | ixgbe_netmap_rxsync(struct netmap_kring *kring, int flags) | ||||
* nic_i = rxr->next_to_check; | * nic_i = rxr->next_to_check; | ||||
* nm_i = kring->nr_hwtail (previous) | * nm_i = kring->nr_hwtail (previous) | ||||
* and | * and | ||||
* nm_i == (nic_i + kring->nkr_hwofs) % ring_size | * nm_i == (nic_i + kring->nkr_hwofs) % ring_size | ||||
* | * | ||||
* rxr->next_to_check is set to 0 on a ring reinit | * rxr->next_to_check is set to 0 on a ring reinit | ||||
*/ | */ | ||||
if (netmap_no_pendintr || force_update) { | 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; | uint16_t slot_flags = kring->nkr_slot_flags; | ||||
nic_i = rxr->next_to_check; // or also k2n(kring->nr_hwtail) | nic_i = rxr->next_to_check; // or also k2n(kring->nr_hwtail) | ||||
nm_i = netmap_idx_n2k(kring, nic_i); | nm_i = netmap_idx_n2k(kring, nic_i); | ||||
for (n = 0; ; n++) { | for (n = 0; ; n++) { | ||||
union ixgbe_adv_rx_desc *curr = &rxr->rx_base[nic_i]; | union ixgbe_adv_rx_desc *curr = &rxr->rx_base[nic_i]; | ||||
uint32_t staterr = le32toh(curr->wb.upper.status_error); | uint32_t staterr = le32toh(curr->wb.upper.status_error); | ||||
▲ Show 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | if (nm_i != head) { | ||||
bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map, | bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map, | ||||
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); | BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); | ||||
/* | /* | ||||
* IMPORTANT: we must leave one free slot in the ring, | * IMPORTANT: we must leave one free slot in the ring, | ||||
* so move nic_i back by one unit | * so move nic_i back by one unit | ||||
*/ | */ | ||||
nic_i = nm_prev(nic_i, lim); | 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); | ||||
} | } | ||||
/* tell userspace that there might be new packets */ | /* tell userspace that there might be new packets */ | ||||
nm_rxsync_finalize(kring); | nm_rxsync_finalize(kring); | ||||
return 0; | return 0; | ||||
ring_reset: | ring_reset: | ||||
return netmap_ring_reinit(kring); | return netmap_ring_reinit(kring); | ||||
} | } | ||||
/* | /* | ||||
* The attach routine, called near the end of ixgbe_attach(), | * The attach routine, called near the end of ixgbe_attach(), | ||||
* fills the parameters for netmap_attach() and calls it. | * fills the parameters for netmap_attach() and calls it. | ||||
* It cannot fail, in the worst case (such as no memory) | * It cannot fail, in the worst case (such as no memory) | ||||
* netmap mode will be disabled and the driver will only | * netmap mode will be disabled and the driver will only | ||||
* operate in standard mode. | * operate in standard mode. | ||||
*/ | */ | ||||
static void | void | ||||
ixgbe_netmap_attach(struct adapter *adapter) | ixgbe_netmap_attach(struct adapter *adapter) | ||||
{ | { | ||||
struct netmap_adapter na; | struct netmap_adapter na; | ||||
bzero(&na, sizeof(na)); | bzero(&na, sizeof(na)); | ||||
na.ifp = adapter->ifp; | na.ifp = adapter->ifp; | ||||
na.na_flags = NAF_BDG_MAYSLEEP; | na.na_flags = NAF_BDG_MAYSLEEP; | ||||
Show All 10 Lines |