Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/netmap/ixgbe_netmap.h
Show First 20 Lines • Show All 183 Lines • ▼ Show 20 Lines | ixgbe_netmap_txsync(struct netmap_kring *kring, int flags) | ||||
* interrupts on every tx packet are expensive so request | * interrupts on every tx packet are expensive so request | ||||
* them every half ring, or where NS_REPORT is set | * them every half ring, or where NS_REPORT is set | ||||
*/ | */ | ||||
u_int report_frequency = kring->nkr_num_slots >> 1; | u_int report_frequency = kring->nkr_num_slots >> 1; | ||||
/* device-specific */ | /* device-specific */ | ||||
struct adapter *adapter = ifp->if_softc; | struct adapter *adapter = ifp->if_softc; | ||||
struct tx_ring *txr = &adapter->tx_rings[kring->ring_id]; | struct tx_ring *txr = &adapter->tx_rings[kring->ring_id]; | ||||
int reclaim_tx; | int reclaim_tx, report; | ||||
bus_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map, | bus_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map, | ||||
BUS_DMASYNC_POSTREAD); | BUS_DMASYNC_POSTREAD); | ||||
/* | /* | ||||
* First part: process new packets to send. | * First part: process new packets to send. | ||||
* nm_i is the current index in the netmap ring, | * nm_i is the current index in the netmap ring, | ||||
* nic_i is the corresponding index in the NIC ring. | * nic_i is the corresponding index in the NIC ring. | ||||
Show All 30 Lines | ixgbe_netmap_txsync(struct netmap_kring *kring, int flags) | ||||
nm_i = kring->nr_hwcur; | nm_i = kring->nr_hwcur; | ||||
if (nm_i != head) { /* we have new packets to send */ | if (nm_i != head) { /* we have new packets to send */ | ||||
nic_i = netmap_idx_k2n(kring, nm_i); | nic_i = netmap_idx_k2n(kring, nm_i); | ||||
__builtin_prefetch(&ring->slot[nm_i]); | __builtin_prefetch(&ring->slot[nm_i]); | ||||
__builtin_prefetch(&txr->tx_buffers[nic_i]); | __builtin_prefetch(&txr->tx_buffers[nic_i]); | ||||
for (n = 0; nm_i != head; n++) { | while (nm_i != head) { | ||||
struct netmap_slot *slot = &ring->slot[nm_i]; | struct netmap_slot *slot = &ring->slot[nm_i]; | ||||
u_int len = slot->len; | u_int len = slot->len; | ||||
uint64_t paddr; | uint64_t paddr; | ||||
void *addr = PNMB(na, slot, &paddr); | void *addr = PNMB(na, slot, &paddr); | ||||
/* device-specific */ | /* device-specific */ | ||||
union ixgbe_adv_tx_desc *curr = &txr->tx_base[nic_i]; | union ixgbe_adv_tx_desc *curr = &txr->tx_base[nic_i]; | ||||
struct ixgbe_tx_buf *txbuf = &txr->tx_buffers[nic_i]; | struct ixgbe_tx_buf *txbuf = &txr->tx_buffers[nic_i]; | ||||
int flags = (slot->flags & NS_REPORT || | unsigned int hw_flags = IXGBE_ADVTXD_DTYP_DATA | IXGBE_ADVTXD_DCMD_DEXT | | ||||
nic_i == 0 || nic_i == report_frequency) ? | IXGBE_ADVTXD_DCMD_IFCS; | ||||
IXGBE_TXD_CMD_RS : 0; | u_int totlen = len; | ||||
/* prefetch for next round */ | /* prefetch for next round */ | ||||
__builtin_prefetch(&ring->slot[nm_i + 1]); | __builtin_prefetch(&ring->slot[nm_i + 1]); | ||||
__builtin_prefetch(&txr->tx_buffers[nic_i + 1]); | __builtin_prefetch(&txr->tx_buffers[nic_i + 1]); | ||||
NM_CHECK_ADDR_LEN(na, addr, len); | NM_CHECK_ADDR_LEN(na, addr, len); | ||||
report = (slot->flags & NS_REPORT) || | |||||
nic_i == 0 || | |||||
nic_i == report_frequency; | |||||
if (slot->flags & NS_MOREFRAG) { | |||||
/* There is some duplicated code here, but | |||||
* mixing everything up in the outer loop makes | |||||
* things less transparent, and it also adds | |||||
* unnecessary instructions in the fast path | |||||
*/ | |||||
union ixgbe_adv_tx_desc *first = curr; | |||||
first->read.buffer_addr = htole64(paddr); | |||||
first->read.cmd_type_len = htole32(len | hw_flags); | |||||
bus_dmamap_sync(txr->txtag, txbuf->map, BUS_DMASYNC_PREWRITE); | |||||
/* avoid setting the FCS flag in the | |||||
* descriptors after the first, for safety | |||||
*/ | |||||
hw_flags &= ~IXGBE_ADVTXD_DCMD_IFCS; | |||||
for (;;) { | |||||
nm_i = nm_next(nm_i, lim); | |||||
nic_i = nm_next(nic_i, lim); | |||||
/* remember that we have to ask for a | |||||
* report each time we move past half a | |||||
* ring | |||||
*/ | |||||
report |= nic_i == 0 || | |||||
nic_i == report_frequency; | |||||
if (nm_i == head) { | |||||
/* We do not accept incomplete packets. */ | |||||
return EINVAL; | |||||
} | |||||
slot = &ring->slot[nm_i]; | |||||
len = slot->len; | |||||
addr = PNMB(na, slot, &paddr); | |||||
NM_CHECK_ADDR_LEN(na, addr, len); | |||||
curr = &txr->tx_base[nic_i]; | |||||
txbuf = &txr->tx_buffers[nic_i]; | |||||
totlen += len; | |||||
if (!(slot->flags & NS_MOREFRAG)) | |||||
break; | |||||
if (slot->flags & NS_BUF_CHANGED) { | if (slot->flags & NS_BUF_CHANGED) { | ||||
/* buffer has changed, reload map */ | /* buffer has changed, reload map */ | ||||
netmap_reload_map(na, txr->txtag, txbuf->map, addr); | netmap_reload_map(na, txr->txtag, txbuf->map, addr); | ||||
} | } | ||||
curr->read.buffer_addr = htole64(paddr); | |||||
curr->read.olinfo_status = 0; | |||||
curr->read.cmd_type_len = htole32(len | hw_flags); | |||||
bus_dmamap_sync(txr->txtag, txbuf->map, BUS_DMASYNC_PREWRITE); | |||||
} | |||||
first->read.olinfo_status = | |||||
htole32(totlen << IXGBE_ADVTXD_PAYLEN_SHIFT); | |||||
totlen = 0; | |||||
} | |||||
/* curr/txbuf now always refer to the last descriptor of a packet | |||||
* (which is also the first for single-slot packets) | |||||
* | |||||
* EOP and RS must be set only in this descriptor. | |||||
*/ | |||||
hw_flags |= IXGBE_TXD_CMD_EOP | (report ? IXGBE_TXD_CMD_RS : 0); | |||||
if (slot->flags & NS_BUF_CHANGED) { | |||||
/* buffer has changed, reload map */ | |||||
netmap_reload_map(na, txr->txtag, txbuf->map, addr); | |||||
} | |||||
slot->flags &= ~(NS_REPORT | NS_BUF_CHANGED); | slot->flags &= ~(NS_REPORT | NS_BUF_CHANGED); | ||||
/* Fill the slot in the NIC ring. */ | /* Fill the slot in the NIC ring. */ | ||||
/* Use legacy descriptor, they are faster? */ | |||||
curr->read.buffer_addr = htole64(paddr); | curr->read.buffer_addr = htole64(paddr); | ||||
curr->read.olinfo_status = 0; | curr->read.olinfo_status = htole32(totlen << IXGBE_ADVTXD_PAYLEN_SHIFT); | ||||
curr->read.cmd_type_len = htole32(len | flags | | curr->read.cmd_type_len = htole32(len | hw_flags); | ||||
IXGBE_ADVTXD_DCMD_IFCS | IXGBE_TXD_CMD_EOP); | |||||
/* make sure changes to the buffer are synced */ | /* make sure changes to the buffer are synced */ | ||||
bus_dmamap_sync(txr->txtag, txbuf->map, | bus_dmamap_sync(txr->txtag, txbuf->map, BUS_DMASYNC_PREWRITE); | ||||
BUS_DMASYNC_PREWRITE); | |||||
nm_i = nm_next(nm_i, lim); | nm_i = nm_next(nm_i, lim); | ||||
nic_i = nm_next(nic_i, lim); | nic_i = nm_next(nic_i, lim); | ||||
} | } | ||||
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, | ||||
▲ Show 20 Lines • Show All 110 Lines • ▼ Show 20 Lines | ixgbe_netmap_rxsync(struct netmap_kring *kring, int flags) | ||||
* 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 || IXGBE_IS_VF(adapter) ) ? 0 : 4; | int crclen = (ix_crcstrip || IXGBE_IS_VF(adapter) ) ? 0 : 4; | ||||
u_int new_hwtail = (u_int)-1; | |||||
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); | ||||
int complete; /* did we see a complete packet ? */ | |||||
if ((staterr & IXGBE_RXD_STAT_DD) == 0) | if ((staterr & IXGBE_RXD_STAT_DD) == 0) | ||||
break; | break; | ||||
ring->slot[nm_i].len = le16toh(curr->wb.upper.length) - crclen; | ring->slot[nm_i].len = le16toh(curr->wb.upper.length) - crclen; | ||||
ring->slot[nm_i].flags = 0; | complete = staterr & IXGBE_RXD_STAT_EOP; | ||||
ring->slot[nm_i].flags = complete ? 0 : NS_MOREFRAG; | |||||
bus_dmamap_sync(rxr->ptag, | bus_dmamap_sync(rxr->ptag, | ||||
rxr->rx_buffers[nic_i].pmap, BUS_DMASYNC_POSTREAD); | rxr->rx_buffers[nic_i].pmap, BUS_DMASYNC_POSTREAD); | ||||
nm_i = nm_next(nm_i, lim); | nm_i = nm_next(nm_i, lim); | ||||
nic_i = nm_next(nic_i, lim); | nic_i = nm_next(nic_i, lim); | ||||
if (complete) { | |||||
erj: the braces here are unnecessary | |||||
new_hwtail = nm_i; | |||||
} | } | ||||
} | |||||
if (n) { /* update the state variables */ | if (n) { /* update the state variables */ | ||||
if (netmap_no_pendintr && !force_update) { | if (netmap_no_pendintr && !force_update) { | ||||
/* diagnostics */ | /* diagnostics */ | ||||
ix_rx_miss ++; | ix_rx_miss ++; | ||||
ix_rx_miss_bufs += n; | ix_rx_miss_bufs += n; | ||||
} | } | ||||
rxr->next_to_check = nic_i; | rxr->next_to_check = nic_i; | ||||
kring->nr_hwtail = nm_i; | if (new_hwtail != (u_int)-1) | ||||
kring->nr_hwtail = new_hwtail; | |||||
} | } | ||||
kring->nr_kflags &= ~NKR_PENDINTR; | kring->nr_kflags &= ~NKR_PENDINTR; | ||||
} | } | ||||
/* | /* | ||||
* Second part: skip past packets that userspace has released. | * Second part: skip past packets that userspace has released. | ||||
* (kring->nr_hwcur to kring->rhead excluded), | * (kring->nr_hwcur to kring->rhead excluded), | ||||
* and make the buffers available for reception. | * and make the buffers available for reception. | ||||
▲ Show 20 Lines • Show All 56 Lines • ▼ Show 20 Lines | |||||
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 | NAF_MOREFRAG; | ||||
na.num_tx_desc = adapter->num_tx_desc; | na.num_tx_desc = adapter->num_tx_desc; | ||||
na.num_rx_desc = adapter->num_rx_desc; | na.num_rx_desc = adapter->num_rx_desc; | ||||
na.nm_txsync = ixgbe_netmap_txsync; | na.nm_txsync = ixgbe_netmap_txsync; | ||||
na.nm_rxsync = ixgbe_netmap_rxsync; | na.nm_rxsync = ixgbe_netmap_rxsync; | ||||
na.nm_register = ixgbe_netmap_reg; | na.nm_register = ixgbe_netmap_reg; | ||||
na.num_tx_rings = na.num_rx_rings = adapter->num_queues; | na.num_tx_rings = na.num_rx_rings = adapter->num_queues; | ||||
na.nm_intr = ixgbe_netmap_intr; | na.nm_intr = ixgbe_netmap_intr; | ||||
netmap_attach(&na); | netmap_attach(&na); | ||||
} | } | ||||
/* end of file */ | /* end of file */ |
the braces here are unnecessary