Author: vmaffione
Date: Wed Aug 12 14:45:31 2020
New Revision: 364165
URL: https://svnweb.freebsd.org/changeset/base/364165

Log:
  iflib: netmap: improve rxsync to support IFLIB_HAS_RXCQ
  
  For drivers with IFLIB_HAS_RXCQ set, there is a separate completion
  queue. In this case, the netmap rxsync routine needs to update
  rxq->ifr_cq_cidx in the same way it is updated by iflib_rxeof().
  This improves the situation for vmx(4) and bnxt(4) drivers, which
  use iflib and have the IFLIB_HAS_RXCQ bit set.
  
  PR:   248494
  MFC after:    3 weeks

Modified:
  head/sys/net/iflib.c
  head/sys/net/iflib.h

Modified: head/sys/net/iflib.c
==============================================================================
--- head/sys/net/iflib.c        Wed Aug 12 14:17:38 2020        (r364164)
+++ head/sys/net/iflib.c        Wed Aug 12 14:45:31 2020        (r364165)
@@ -424,7 +424,7 @@ struct iflib_rxq {
        struct pfil_head        *pfil;
        /*
         * If there is a separate completion queue (IFLIB_HAS_RXCQ), this is
-        * the command queue consumer index.  Otherwise it's unused.
+        * the completion queue consumer index.  Otherwise it's unused.
         */
        qidx_t          ifr_cq_cidx;
        uint16_t        ifr_id;
@@ -1077,9 +1077,12 @@ iflib_netmap_rxsync(struct netmap_kring *kring, int fl
        int force_update = (flags & NAF_FORCE_READ) || kring->nr_kflags & 
NKR_PENDINTR;
 
        if_ctx_t ctx = ifp->if_softc;
+       if_shared_ctx_t sctx = ctx->ifc_sctx;
+       if_softc_ctx_t scctx = &ctx->ifc_softc_ctx;
        iflib_rxq_t rxq = &ctx->ifc_rxqs[kring->ring_id];
        iflib_fl_t fl = &rxq->ifr_fl[0];
        struct if_rxd_info ri;
+       qidx_t *cidxp;
 
        /*
         * netmap only uses free list 0, to avoid out of order consumption
@@ -1093,40 +1096,56 @@ iflib_netmap_rxsync(struct netmap_kring *kring, int fl
         * 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
+        * nic_i is the index of the next received packet in the NIC ring
+        * (or in the free list 0 if IFLIB_HAS_RXCQ is set), and they may
+        * differ in case if_init() has been called while
         * in netmap mode. For the receive ring we have
         *
-        *      nic_i = rxr->next_check;
+        *      nic_i = fl->ifl_cidx;
         *      nm_i = kring->nr_hwtail (previous)
         * and
         *      nm_i == (nic_i + kring->nkr_hwofs) % ring_size
         *
-        * rxr->next_check is set to 0 on a ring reinit
+        * fl->ifl_cidx is set to 0 on a ring reinit
         */
        if (netmap_no_pendintr || force_update) {
                uint32_t hwtail_lim = nm_prev(kring->nr_hwcur, lim);
+               bool have_rxcq = sctx->isc_flags & IFLIB_HAS_RXCQ;
                int crclen = iflib_crcstrip ? 0 : 4;
                int error, avail;
 
+               /*
+                * For the free list consumer index, we use the same
+                * logic as in iflib_rxeof().
+                */
+               if (have_rxcq)
+                       cidxp = &rxq->ifr_cq_cidx;
+               else
+                       cidxp = &fl->ifl_cidx;
+               avail = ctx->isc_rxd_available(ctx->ifc_softc,
+                   rxq->ifr_id, *cidxp, USHRT_MAX);
+
                nic_i = fl->ifl_cidx;
                nm_i = netmap_idx_n2k(kring, nic_i);
-               avail = ctx->isc_rxd_available(ctx->ifc_softc,
-                   rxq->ifr_id, nic_i, USHRT_MAX);
                for (n = 0; avail > 0 && nm_i != hwtail_lim; n++, avail--) {
                        rxd_info_zero(&ri);
                        ri.iri_frags = rxq->ifr_frags;
                        ri.iri_qsidx = kring->ring_id;
                        ri.iri_ifp = ctx->ifc_ifp;
-                       ri.iri_cidx = nic_i;
+                       ri.iri_cidx = *cidxp;
 
                        error = ctx->isc_rxd_pkt_get(ctx->ifc_softc, &ri);
                        ring->slot[nm_i].len = error ? 0 : ri.iri_len - crclen;
                        ring->slot[nm_i].flags = 0;
+                       if (have_rxcq) {
+                               *cidxp = ri.iri_cidx;
+                               while (*cidxp >= scctx->isc_nrxd[0])
+                                       *cidxp -= scctx->isc_nrxd[0];
+                       }
                        bus_dmamap_sync(fl->ifl_buf_tag,
                            fl->ifl_sds.ifsd_map[nic_i], BUS_DMASYNC_POSTREAD);
                        nm_i = nm_next(nm_i, lim);
-                       nic_i = nm_next(nic_i, lim);
+                       fl->ifl_cidx = nic_i = nm_next(nic_i, lim);
                }
                if (n) { /* update the state variables */
                        if (netmap_no_pendintr && !force_update) {
@@ -1134,7 +1153,6 @@ iflib_netmap_rxsync(struct netmap_kring *kring, int fl
                                iflib_rx_miss ++;
                                iflib_rx_miss_bufs += n;
                        }
-                       fl->ifl_cidx = nic_i;
                        kring->nr_hwtail = nm_i;
                }
                kring->nr_kflags &= ~NKR_PENDINTR;

Modified: head/sys/net/iflib.h
==============================================================================
--- head/sys/net/iflib.h        Wed Aug 12 14:17:38 2020        (r364164)
+++ head/sys/net/iflib.h        Wed Aug 12 14:45:31 2020        (r364165)
@@ -297,7 +297,7 @@ typedef enum {
 } iflib_intr_type_t;
 
 /*
- * Interface has a separate command queue for RX
+ * Interface has a separate completion queue for RX
  */
 #define IFLIB_HAS_RXCQ         0x01
 /*
@@ -309,7 +309,7 @@ typedef enum {
  */
 #define IFLIB_IS_VF            0x04
 /*
- * Interface has a separate command queue for TX
+ * Interface has a separate completion queue for TX
  */
 #define IFLIB_HAS_TXCQ         0x08
 /*
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to