* Reconcile kernel and user view of the transmit ring. * * All information is in the kring. * Userspace wants to send packets up to the one before kring->rhead, * 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. * * The caller (netmap) guarantees that there is
| 957 | * methods should be handled by the individual drivers. |
| 958 | */ |
| 959 | static int |
| 960 | iflib_netmap_txsync(struct netmap_kring *kring, int flags) |
| 961 | { |
| 962 | struct netmap_adapter *na = kring->na; |
| 963 | if_t ifp = na->ifp; |
| 964 | struct netmap_ring *ring = kring->ring; |
| 965 | u_int nm_i; /* index into the netmap kring */ |
| 966 | u_int nic_i; /* index into the NIC ring */ |
| 967 | u_int n; |
| 968 | u_int const lim = kring->nkr_num_slots - 1; |
| 969 | u_int const head = kring->rhead; |
| 970 | struct if_pkt_info pi; |
| 971 | |
| 972 | /* |
| 973 | * interrupts on every tx packet are expensive so request |
| 974 | * them every half ring, or where NS_REPORT is set |
| 975 | */ |
| 976 | u_int report_frequency = kring->nkr_num_slots >> 1; |
| 977 | /* device-specific */ |
| 978 | if_ctx_t ctx = ifp->if_softc; |
| 979 | iflib_txq_t txq = &ctx->ifc_txqs[kring->ring_id]; |
| 980 | |
| 981 | bus_dmamap_sync(txq->ift_ifdi->idi_tag, txq->ift_ifdi->idi_map, |
| 982 | BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); |
| 983 | |
| 984 | /* |
| 985 | * First part: process new packets to send. |
| 986 | * nm_i is the current index in the netmap kring, |
| 987 | * nic_i is the corresponding index in the NIC ring. |
| 988 | * |
| 989 | * If we have packets to send (nm_i != head) |
| 990 | * iterate over the netmap ring, fetch length and update |
| 991 | * the corresponding slot in the NIC ring. Some drivers also |
| 992 | * need to update the buffer's physical address in the NIC slot |
| 993 | * even NS_BUF_CHANGED is not set (PNMB computes the addresses). |
| 994 | * |
| 995 | * The netmap_reload_map() calls is especially expensive, |
| 996 | * even when (as in this case) the tag is 0, so do only |
| 997 | * when the buffer has actually changed. |
| 998 | * |
| 999 | * If possible do not set the report/intr bit on all slots, |
| 1000 | * but only a few times per ring or when NS_REPORT is set. |
| 1001 | * |
| 1002 | * Finally, on 10G and faster drivers, it might be useful |
| 1003 | * to prefetch the next slot and txr entry. |
| 1004 | */ |
| 1005 | |
| 1006 | nm_i = kring->nr_hwcur; |
| 1007 | if (nm_i != head) { /* we have new packets to send */ |
| 1008 | uint32_t pkt_len = 0, seg_idx = 0; |
| 1009 | int nic_i_start = -1, flags = 0; |
| 1010 | pkt_info_zero(&pi); |
| 1011 | pi.ipi_segs = txq->ift_segs; |
| 1012 | pi.ipi_qsidx = kring->ring_id; |
| 1013 | nic_i = netmap_idx_k2n(kring, nm_i); |
| 1014 | |
| 1015 | __builtin_prefetch(&ring->slot[nm_i]); |
| 1016 | __builtin_prefetch(&txq->ift_sds.ifsd_m[nic_i]); |
nothing calls this directly
no test coverage detected