Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/xen/xen add support for scatter-gather also for fro...



details:   https://anonhg.NetBSD.org/src/rev/a70c11942350
branches:  trunk
changeset: 971768:a70c11942350
user:      jdolecek <jdolecek%NetBSD.org@localhost>
date:      Sun May 03 17:56:19 2020 +0000

description:
add support for scatter-gather also for frontend Rx path (backend -> frontend)

enable ETHERCAP_JUMBO_MTU and feature-sg

diffstat:

 sys/arch/xen/xen/xennetback_xenbus.c |  324 +++++++++++++++++++++-------------
 1 files changed, 200 insertions(+), 124 deletions(-)

diffs (truncated from 452 to 300 lines):

diff -r 3f4af4acae77 -r a70c11942350 sys/arch/xen/xen/xennetback_xenbus.c
--- a/sys/arch/xen/xen/xennetback_xenbus.c      Sun May 03 17:54:28 2020 +0000
+++ b/sys/arch/xen/xen/xennetback_xenbus.c      Sun May 03 17:56:19 2020 +0000
@@ -1,4 +1,4 @@
-/*      $NetBSD: xennetback_xenbus.c,v 1.102 2020/05/02 11:28:02 jdolecek Exp $      */
+/*      $NetBSD: xennetback_xenbus.c,v 1.103 2020/05/03 17:56:19 jdolecek Exp $      */
 
 /*
  * Copyright (c) 2006 Manuel Bouyer.
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xennetback_xenbus.c,v 1.102 2020/05/02 11:28:02 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xennetback_xenbus.c,v 1.103 2020/05/03 17:56:19 jdolecek Exp $");
 
 #include "opt_xen.h"
 
@@ -60,8 +60,6 @@
 
 #include <uvm/uvm.h>
 
-/* #define notyet 1 */
-
 /*
  * Backend network device driver for Xen.
  */
@@ -263,11 +261,7 @@
        /* create pseudo-interface */
        aprint_verbose_ifnet(ifp, "Ethernet address %s\n",
            ether_sprintf(xneti->xni_enaddr));
-       xneti->xni_ec.ec_capabilities |= ETHERCAP_VLAN_MTU
-#ifdef notyet
-               | ETHERCAP_JUMBO_MTU
-#endif
-       ;
+       xneti->xni_ec.ec_capabilities |= ETHERCAP_VLAN_MTU | ETHERCAP_JUMBO_MTU;
        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
        ifp->if_snd.ifq_maxlen =
            uimax(ifqmaxlen, NET_TX_RING_SIZE * 2);
@@ -327,7 +321,6 @@
                            xbusd->xbusd_path, err);
                        goto abort_xbt;
                }
-#if notyet
                err = xenbus_printf(xbt, xbusd->xbusd_path,
                    "feature-sg", "%d", 1);
                if (err) {
@@ -336,7 +329,6 @@
                            xbusd->xbusd_path, err);
                        goto abort_xbt;
                }
-#endif
        } while ((err = xenbus_transaction_end(xbt, 0)) == EAGAIN);
        if (err) {
                aprint_error_ifnet(ifp,
@@ -678,21 +670,22 @@
 }
 
 static int
-xennetback_copy(struct ifnet *ifp, gnttab_copy_t *gop, int copycnt)
+xennetback_copy(struct ifnet *ifp, gnttab_copy_t *gop, int copycnt,
+    const char *dir)
 {
        /*
         * Copy the data and ack it. Delaying it until the mbuf is
         * freed will stall transmit.
         */
        if (HYPERVISOR_grant_table_op(GNTTABOP_copy, gop, copycnt) != 0) {
-               printf("%s: GNTTABOP_copy Tx failed", ifp->if_xname);
+               printf("%s: GNTTABOP_copy %s failed", ifp->if_xname, dir);
                return EINVAL;
        }
 
        for (int i = 0; i < copycnt; i++) {
                if (gop->status != GNTST_okay) {
-                       printf("%s GNTTABOP_copy[%d] Tx %d\n",
-                           ifp->if_xname, i, gop->status);
+                       printf("%s GNTTABOP_copy[%d] %s %d\n",
+                           ifp->if_xname, i, dir, gop->status);
                        return EINVAL;
                }
        }
@@ -758,7 +751,7 @@
                        KASSERT(copycnt <= NB_XMIT_PAGES_BATCH);
                        if (copycnt == NB_XMIT_PAGES_BATCH) {
                                if (xennetback_copy(ifp, xneti->xni_gop_copy,
-                                   copycnt) != 0)
+                                   copycnt, "Tx") != 0)
                                        goto abort;
                                copycnt = 0;
                        }
@@ -791,7 +784,7 @@
                KASSERT(goff == xst->xs_tx_size);
        }
        if (copycnt > 0) {
-               if (xennetback_copy(ifp, xneti->xni_gop_copy, copycnt) != 0)
+               if (xennetback_copy(ifp, xneti->xni_gop_copy, copycnt, "Tx"))
                        goto abort;
                copycnt = 0;
        }
@@ -1058,19 +1051,151 @@
 }
 
 static void
+xennetback_rx_copy_process(struct ifnet *ifp, struct xnetback_instance *xneti,
+       int queued, int copycnt)
+{
+       int notify;
+       struct xnetback_xstate *xst;
+
+       if (xennetback_copy(ifp, xneti->xni_gop_copy, copycnt, "Rx") != 0) {
+               /* message already displayed */
+               goto free_mbufs;
+       }
+
+       /* update pointer */
+       xen_rmb();
+       xneti->xni_rxring.req_cons += queued;
+       xneti->xni_rxring.rsp_prod_pvt += queued;
+       RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&xneti->xni_rxring, notify);
+
+       /* send event */
+       if (notify) {
+               xen_rmb();
+               XENPRINTF(("%s receive event\n",
+                   xneti->xni_if.if_xname));
+               hypervisor_notify_via_evtchn(xneti->xni_evtchn);
+       }
+
+free_mbufs:
+       /* now that data was copied we can free the mbufs */
+       for (int j = 0; j < queued; j++) {
+               xst = &xneti->xni_xstate[j];
+               if (xst->xs_loaded) {
+                       bus_dmamap_unload(xneti->xni_xbusd->xbusd_dmat,
+                           xst->xs_dmamap);
+                       xst->xs_loaded = false;
+               }
+               if (xst->xs_m != NULL) {
+                       m_freem(xst->xs_m);
+                       xst->xs_m = NULL;
+               }
+       }
+}
+
+static void
+xennetback_rx_copy_queue(struct xnetback_instance *xneti,
+    struct xnetback_xstate *xst0, int rsp_prod_pvt, int *queued, int *copycntp)
+{
+       struct xnetback_xstate *xst = xst0;
+       gnttab_copy_t *gop;
+       struct netif_rx_request rxreq;
+       netif_rx_response_t *rxresp;
+       paddr_t ma;
+       size_t goff, segoff, segsize, take, totsize;
+       int copycnt = *copycntp, reqcnt = *queued;
+       const bus_dmamap_t dm = xst0->xs_dmamap;
+       const bool multiseg = (dm->dm_nsegs > 1);
+
+       KASSERT(xst0 == &xneti->xni_xstate[reqcnt]);
+
+       RING_COPY_REQUEST(&xneti->xni_rxring,
+           xneti->xni_rxring.req_cons + reqcnt, &rxreq);
+       goff = 0;
+       rxresp = RING_GET_RESPONSE(&xneti->xni_rxring, rsp_prod_pvt + reqcnt);
+       reqcnt++;
+
+       rxresp->id = rxreq.id;
+       rxresp->offset = 0;
+       if ((xst0->xs_m->m_pkthdr.csum_flags & XN_M_CSUM_SUPPORTED) != 0) {
+               rxresp->flags = NETRXF_csum_blank;
+       } else {
+               rxresp->flags = NETRXF_data_validated;
+       }
+       if (multiseg)
+               rxresp->flags |= NETRXF_more_data;
+
+       totsize = xst0->xs_m->m_pkthdr.len;
+
+       /*
+        * Arrange for the mbuf contents to be copied into one or more
+        * provided memory pages.
+        */
+       for (int seg = 0; seg < dm->dm_nsegs; seg++) {
+               ma = dm->dm_segs[seg].ds_addr;
+               segsize = dm->dm_segs[seg].ds_len;
+               segoff = 0;
+
+               while (segoff < segsize) {
+                       take = uimin(PAGE_SIZE - goff, segsize - segoff);
+                       KASSERT(take <= totsize);
+
+                       /* add copy request */
+                       gop = &xneti->xni_gop_copy[copycnt++];
+                       gop->flags = GNTCOPY_dest_gref;
+                       gop->source.offset = (ma & PAGE_MASK) + segoff;
+                       gop->source.domid = DOMID_SELF;
+                       gop->source.u.gmfn = ma >> PAGE_SHIFT;
+
+                       gop->dest.u.ref = rxreq.gref;
+                       gop->dest.offset = goff;
+                       gop->dest.domid = xneti->xni_domid;
+
+                       gop->len = take;
+
+                       segoff += take;
+                       goff += take;
+                       totsize -= take;
+
+                       if (goff == PAGE_SIZE && totsize > 0) {
+                               rxresp->status = goff;
+
+                               /* Take next grant */
+                               RING_COPY_REQUEST(&xneti->xni_rxring,
+                                   xneti->xni_rxring.req_cons + reqcnt,
+                                   &rxreq);
+                               goff = 0;
+                               rxresp = RING_GET_RESPONSE(&xneti->xni_rxring,
+                                   rsp_prod_pvt + reqcnt);
+                               reqcnt++;
+
+                               rxresp->id = rxreq.id;
+                               rxresp->offset = 0;
+                               rxresp->flags = NETRXF_more_data;
+
+                               xst++;
+                               xst->xs_m = NULL;
+                       }
+               }
+       }
+       rxresp->flags &= ~NETRXF_more_data;
+       rxresp->status = goff;
+       KASSERT(totsize == 0);
+
+       KASSERT(copycnt > *copycntp);
+       KASSERT(reqcnt > *queued);
+       *copycntp = copycnt;
+       *queued = reqcnt;
+}
+
+static void
 xennetback_ifsoftstart_copy(struct xnetback_instance *xneti)
 {
        struct ifnet *ifp = &xneti->xni_if;
        struct mbuf *m;
-       paddr_t xmit_ma;
-       int i, j;
-       netif_rx_response_t *rxresp;
-       netif_rx_request_t rxreq;
-       RING_IDX req_prod, resp_prod;
-       int do_event = 0;
-       gnttab_copy_t *gop;
+       int queued = 0;
+       RING_IDX req_prod, rsp_prod_pvt;
        struct xnetback_xstate *xst;
-       int id;
+       int copycnt = 0;
        bool abort;
 
        XENPRINTF(("xennetback_ifsoftstart_copy "));
@@ -1083,22 +1208,26 @@
        while (!IFQ_IS_EMPTY(&ifp->if_snd)) {
                XENPRINTF(("pkt\n"));
                req_prod = xneti->xni_rxring.sring->req_prod;
-               resp_prod = xneti->xni_rxring.rsp_prod_pvt;
+               rsp_prod_pvt = xneti->xni_rxring.rsp_prod_pvt;
                xen_rmb();
 
-               gop = xneti->xni_gop_copy;
                abort = false;
-               for (i = 0; i < NB_XMIT_PAGES_BATCH; i++) {
-                       if (__predict_false(
-                           req_prod == xneti->xni_rxring.req_cons ||
-                           xneti->xni_rxring.req_cons - resp_prod ==
-                           NET_RX_RING_SIZE)) {
+               KASSERT(queued == 0);
+               KASSERT(copycnt == 0);
+               while (copycnt < NB_XMIT_PAGES_BATCH) {
+#define XN_RING_FULL(cnt)      \
+                       req_prod == xneti->xni_rxring.req_cons + (cnt) ||  \
+                       xneti->xni_rxring.req_cons - (rsp_prod_pvt + cnt) ==  \
+                       NET_RX_RING_SIZE
+
+                       if (__predict_false(XN_RING_FULL(1))) {
                                /* out of ring space */
                                XENPRINTF(("xennetback_ifstart: ring full "
-                                   "req_prod 0x%x req_cons 0x%x resp_prod "
+                                   "req_prod 0x%x req_cons 0x%x rsp_prod_pvt "
                                    "0x%x\n",
-                                   req_prod, xneti->xni_rxring.req_cons,
-                                   resp_prod));
+                                   req_prod,
+                                   xneti->xni_rxring.req_cons + queued,
+                                   rsp_prod_pvt + queued));
                                abort = true;
                                break;
                        }
@@ -1107,7 +1236,8 @@
                        if (m == NULL)



Home | Main Index | Thread Index | Old Index