Date: Tue, 21 Jul 2015 14:19:04 GMT From: stefano@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r288617 - in soc2015/stefano/ptnetmap/stable/10/sys: dev/netmap modules/netmap net Message-ID: <201507211419.t6LEJ4Oa077713@socsvn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: stefano Date: Tue Jul 21 14:19:04 2015 New Revision: 288617 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=288617 Log: add netmap with ptnetmap support (virtio, e1000) - add netmap_virt.h (ex paravirt.h) contains: - CSB definition (shared memory between host/guest) - ptnetmap functions declaration (host/guest) - ptnetmap-memdev ID, register and routines - add ptnetmap.c contains ptnetmap implementation - OS independent (FreeBSD/linux) Added: soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/netmap_virt.h soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/ptnetmap.c Modified: soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/if_em_netmap.h soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/if_igb_netmap.h soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/if_lem_netmap.h soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/if_re_netmap.h soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/if_vtnet_netmap.h soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/ixgbe_netmap.h soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/netmap.c soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/netmap_freebsd.c soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/netmap_generic.c soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/netmap_kern.h soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/netmap_mem2.c soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/netmap_mem2.h soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/netmap_monitor.c soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/netmap_offloadings.c soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/netmap_pipe.c soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/netmap_vale.c soc2015/stefano/ptnetmap/stable/10/sys/modules/netmap/Makefile soc2015/stefano/ptnetmap/stable/10/sys/net/netmap.h soc2015/stefano/ptnetmap/stable/10/sys/net/netmap_user.h Modified: soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/if_em_netmap.h ============================================================================== --- soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/if_em_netmap.h Tue Jul 21 14:10:22 2015 (r288616) +++ soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/if_em_netmap.h Tue Jul 21 14:19:04 2015 (r288617) @@ -24,7 +24,7 @@ */ /* - * $FreeBSD$ + * $FreeBSD: head/sys/dev/netmap/if_em_netmap.h 238985 2012-08-02 11:59:43Z luigi $ * * netmap support for: em. * @@ -198,8 +198,6 @@ } } - nm_txsync_finalize(kring); - return 0; } @@ -217,7 +215,7 @@ u_int nic_i; /* index into the NIC ring */ u_int n; u_int const lim = kring->nkr_num_slots - 1; - u_int const head = nm_rxsync_prologue(kring); + u_int const head = kring->rhead; int force_update = (flags & NAF_FORCE_READ) || kring->nr_kflags & NKR_PENDINTR; /* device-specific */ @@ -303,9 +301,6 @@ E1000_WRITE_REG(&adapter->hw, E1000_RDT(rxr->me), nic_i); } - /* tell userspace that there might be new packets */ - nm_rxsync_finalize(kring); - return 0; ring_reset: Modified: soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/if_igb_netmap.h ============================================================================== --- soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/if_igb_netmap.h Tue Jul 21 14:10:22 2015 (r288616) +++ soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/if_igb_netmap.h Tue Jul 21 14:19:04 2015 (r288617) @@ -24,7 +24,7 @@ */ /* - * $FreeBSD$ + * $FreeBSD: head/sys/dev/netmap/if_igb_netmap.h 256200 2013-10-09 17:32:52Z jfv $ * * Netmap support for igb, partly contributed by Ahmed Kooli * For details on netmap support please see ixgbe_netmap.h @@ -180,8 +180,6 @@ kring->nr_hwtail = nm_prev(netmap_idx_n2k(kring, nic_i), lim); } - nm_txsync_finalize(kring); - return 0; } @@ -199,7 +197,7 @@ u_int nic_i; /* index into the NIC ring */ u_int n; u_int const lim = kring->nkr_num_slots - 1; - u_int const head = nm_rxsync_prologue(kring); + u_int const head = kring->rhead; int force_update = (flags & NAF_FORCE_READ) || kring->nr_kflags & NKR_PENDINTR; /* device-specific */ @@ -283,9 +281,6 @@ E1000_WRITE_REG(&adapter->hw, E1000_RDT(rxr->me), nic_i); } - /* tell userspace that there might be new packets */ - nm_rxsync_finalize(kring); - return 0; ring_reset: Modified: soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/if_lem_netmap.h ============================================================================== --- soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/if_lem_netmap.h Tue Jul 21 14:10:22 2015 (r288616) +++ soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/if_lem_netmap.h Tue Jul 21 14:19:04 2015 (r288617) @@ -25,7 +25,7 @@ /* - * $FreeBSD$ + * $FreeBSD: head/sys/dev/netmap/if_lem_netmap.h 271849 2014-09-19 03:51:26Z glebius $ * * netmap support for: lem * @@ -38,6 +38,7 @@ #include <vm/vm.h> #include <vm/pmap.h> /* vtophys ? */ #include <dev/netmap/netmap_kern.h> +#include <dev/netmap/netmap_virt.h> extern int netmap_adaptive_io; @@ -302,8 +303,6 @@ kring->nr_hwtail = nm_prev(netmap_idx_n2k(kring, nic_i), lim); } - nm_txsync_finalize(kring); - return 0; } @@ -321,7 +320,7 @@ u_int nic_i; /* index into the NIC ring */ u_int n; u_int const lim = kring->nkr_num_slots - 1; - u_int const head = nm_rxsync_prologue(kring); + u_int const head = kring->rhead; int force_update = (flags & NAF_FORCE_READ) || kring->nr_kflags & NKR_PENDINTR; /* device-specific */ @@ -466,15 +465,262 @@ E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), nic_i); } - /* tell userspace that there might be new packets */ - nm_rxsync_finalize(kring); - return 0; ring_reset: return netmap_ring_reinit(kring); } +#if defined (NIC_PTNETMAP) && defined (WITH_PTNETMAP_GUEST) +static uint32_t lem_netmap_ptctl(struct ifnet *, uint32_t); + +static int +lem_ptnetmap_config(struct netmap_adapter *na, + u_int *txr, u_int *txd, u_int *rxr, u_int *rxd) +{ + struct ifnet *ifp = na->ifp; + struct adapter *adapter = ifp->if_softc; + struct paravirt_csb *csb = adapter->csb; + int ret; + + if (csb == NULL) + return EINVAL; + + ret = lem_netmap_ptctl(ifp, NET_PARAVIRT_PTCTL_CONFIG); + if (ret) + return ret; + + *txr = 1; //*txr = csb->num_tx_rings; + *rxr = 1; //*rxr = csb->num_rx_rings; + *txd = csb->num_tx_slots; + *rxd = csb->num_rx_slots; + + D("txr %u rxr %u txd %u rxd %u", + *txr, *rxr, *txd, *rxd); + + return 0; +} + +static int +lem_ptnetmap_txsync(struct netmap_kring *kring, int flags) +{ + struct netmap_adapter *na = kring->na; + //u_int ring_nr = kring->ring_id; + struct ifnet *ifp = na->ifp; + struct adapter *adapter = ifp->if_softc; + struct paravirt_csb *csb = adapter->csb; + bool send_kick = false; + + /* Disable notifications */ + csb->guest_need_txkick = 0; + + /* + * First part: process new packets to send. + */ + kring->nr_hwcur = csb->tx_ring.hwcur; + ptnetmap_guest_write_kring_csb(&csb->tx_ring, kring->rcur, kring->rhead); + if (kring->rhead != kring->nr_hwcur) { + send_kick = true; + } + + /* Send kick to the host if it needs them */ + if ((send_kick && ACCESS_ONCE(csb->host_need_txkick)) || (flags & NAF_FORCE_RECLAIM)) { + csb->tx_ring.sync_flags = flags; + E1000_WRITE_REG(&adapter->hw, E1000_TDT(0), 0); + } + + /* + * Second part: reclaim buffers for completed transmissions. + */ + if (flags & NAF_FORCE_RECLAIM || nm_kr_txempty(kring)) { + ptnetmap_guest_read_kring_csb(&csb->tx_ring, &kring->nr_hwcur, &kring->nr_hwtail, kring->nkr_num_slots); + } + + /* + * Ring full. The user thread will go to sleep and + * we need a notification (interrupt) from the NIC, + * whene there is free space. + */ + if (kring->rcur == kring->nr_hwtail) { + /* Reenable notifications. */ + csb->guest_need_txkick = 1; + /* Double check */ + ptnetmap_guest_read_kring_csb(&csb->tx_ring, &kring->nr_hwcur, &kring->nr_hwtail, kring->nkr_num_slots); + /* If there is new free space, disable notifications */ + if (kring->rcur != kring->nr_hwtail) { + csb->guest_need_txkick = 0; + } + } + + ND("TX - CSB: head:%u cur:%u hwtail:%u - KRING: head:%u cur:%u", + csb->tx_ring.head, csb->tx_ring.cur, csb->tx_ring.hwtail, kring->rhead, kring->rcur); + + return 0; +} + +static int +lem_ptnetmap_rxsync(struct netmap_kring *kring, int flags) +{ + struct netmap_adapter *na = kring->na; + //u_int ring_nr = kring->ring_id; + struct ifnet *ifp = na->ifp; + struct adapter *adapter = ifp->if_softc; + struct paravirt_csb *csb = adapter->csb; + + int force_update = (flags & NAF_FORCE_READ) || kring->nr_kflags & NKR_PENDINTR; + uint32_t h_hwcur = kring->nr_hwcur, h_hwtail = kring->nr_hwtail; + + /* Disable notifications */ + csb->guest_need_rxkick = 0; + + ptnetmap_guest_read_kring_csb(&csb->rx_ring, &h_hwcur, &h_hwtail, kring->nkr_num_slots); + + /* + * First part: import newly received packets. + */ + if (netmap_no_pendintr || force_update) { + kring->nr_hwtail = h_hwtail; + kring->nr_kflags &= ~NKR_PENDINTR; + } + + /* + * Second part: skip past packets that userspace has released. + */ + kring->nr_hwcur = h_hwcur; + if (kring->rhead != kring->nr_hwcur) { + ptnetmap_guest_write_kring_csb(&csb->rx_ring, kring->rcur, kring->rhead); + /* Send kick to the host if it needs them */ + if (ACCESS_ONCE(csb->host_need_rxkick)) { + csb->rx_ring.sync_flags = flags; + E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), 0); + } + } + + /* + * Ring empty. The user thread will go to sleep and + * we need a notification (interrupt) from the NIC, + * whene there are new packets. + */ + if (kring->rcur == kring->nr_hwtail) { + /* Reenable notifications. */ + csb->guest_need_rxkick = 1; + /* Double check */ + ptnetmap_guest_read_kring_csb(&csb->rx_ring, &kring->nr_hwcur, &kring->nr_hwtail, kring->nkr_num_slots); + /* If there are new packets, disable notifications */ + if (kring->rcur != kring->nr_hwtail) { + csb->guest_need_rxkick = 0; + } + } + + ND("RX - CSB: head:%u cur:%u hwtail:%u - KRING: head:%u cur:%u", + csb->rx_ring.head, csb->rx_ring.cur, csb->rx_ring.hwtail, kring->rhead, kring->rcur); + + return 0; + + +} + +static int +lem_ptnetmap_reg(struct netmap_adapter *na, int onoff) +{ + struct ifnet *ifp = na->ifp; + struct adapter *adapter = ifp->if_softc; + struct paravirt_csb *csb = adapter->csb; + struct netmap_kring *kring; + int ret; + + if (onoff) { + ret = lem_netmap_ptctl(ifp, NET_PARAVIRT_PTCTL_REGIF); + if (ret) + return ret; + + na->na_flags |= NAF_NETMAP_ON; + adapter->ptnetmap_enabled = 1; + /* + * Init ring and kring pointers + * After PARAVIRT_PTCTL_REGIF, the csb contains a snapshot of a + * host kring pointers. + * XXX This initialization is required, because we don't close the + * host port on UNREGIF. + */ + + // Init rx ring + kring = na->rx_rings; + kring->rhead = kring->ring->head = csb->rx_ring.head; + kring->rcur = kring->ring->cur = csb->rx_ring.cur; + kring->nr_hwcur = csb->rx_ring.hwcur; + kring->nr_hwtail = kring->rtail = kring->ring->tail = csb->rx_ring.hwtail; + + // Init tx ring + kring = na->tx_rings; + kring->rhead = kring->ring->head = csb->tx_ring.head; + kring->rcur = kring->ring->cur = csb->tx_ring.cur; + kring->nr_hwcur = csb->tx_ring.hwcur; + kring->nr_hwtail = kring->rtail = kring->ring->tail = csb->tx_ring.hwtail; + } else { + na->na_flags &= ~NAF_NETMAP_ON; + adapter->ptnetmap_enabled = 0; + ret = lem_netmap_ptctl(ifp, NET_PARAVIRT_PTCTL_UNREGIF); + } + + return lem_netmap_reg(na, onoff); +} + + +static int +lem_ptnetmap_bdg_attach(const char *bdg_name, struct netmap_adapter *na) +{ + return EOPNOTSUPP; +} + +static struct paravirt_csb * +lem_netmap_getcsb(struct ifnet *ifp) +{ + struct adapter *adapter = ifp->if_softc; + + return adapter->csb; +} + +static uint32_t +lem_netmap_ptctl(struct ifnet *ifp, uint32_t val) +{ + struct adapter *adapter = ifp->if_softc; + uint32_t ret; + + E1000_WRITE_REG(&adapter->hw, E1000_PTCTL, val); + ret = E1000_READ_REG(&adapter->hw, E1000_PTSTS); + D("PTSTS = %u", ret); + + return ret; +} + + + +static uint32_t +lem_ptnetmap_features(struct adapter *adapter) +{ + uint32_t features; + /* tell the device the features we support */ + E1000_WRITE_REG(&adapter->hw, E1000_PTFEAT, NET_PTN_FEATURES_BASE); + /* get back the acknowledged features */ + features = E1000_READ_REG(&adapter->hw, E1000_PTFEAT); + device_printf(adapter->dev, "netmap passthrough: %s\n", + (features & NET_PTN_FEATURES_BASE) ? "base" : + "none"); + return features; +} + +static struct netmap_pt_guest_ops lem_ptnetmap_ops = { + .nm_getcsb = lem_netmap_getcsb, + .nm_ptctl = lem_netmap_ptctl, +}; +#elif defined (NIC_PTNETMAP) +#warning "if_lem supports ptnetmap but netmap does not support it" +#warning "(configure netmap with passthrough support)" +#elif defined (WITH_PTNETMAP_GUEST) +#warning "netmap supports ptnetmap but e1000 does not support it" +#warning "(configure if_lem with passthrough support)" +#endif /* NIC_PTNETMAP && WITH_PTNETMAP_GUEST */ static void lem_netmap_attach(struct adapter *adapter) @@ -491,7 +737,19 @@ na.nm_rxsync = lem_netmap_rxsync; na.nm_register = lem_netmap_reg; na.num_tx_rings = na.num_rx_rings = 1; - netmap_attach(&na); +#if defined (NIC_PTNETMAP) && defined (WITH_PTNETMAP_GUEST) + /* XXX: check if the device support ptnetmap (now we use PARA_SUBDEV) */ + if ((adapter->hw.subsystem_device_id == E1000_PARA_SUBDEV) && + (lem_ptnetmap_features(adapter) & NET_PTN_FEATURES_BASE)) { + na.nm_config = lem_ptnetmap_config; + na.nm_register = lem_ptnetmap_reg; + na.nm_txsync = lem_ptnetmap_txsync; + na.nm_rxsync = lem_ptnetmap_rxsync; + na.nm_bdg_attach = lem_ptnetmap_bdg_attach; /* XXX */ + netmap_pt_guest_attach(&na, &lem_ptnetmap_ops); + } else +#endif /* NIC_PTNETMAP && defined WITH_PTNETMAP_GUEST */ + netmap_attach(&na); } /* end of file */ Modified: soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/if_re_netmap.h ============================================================================== --- soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/if_re_netmap.h Tue Jul 21 14:10:22 2015 (r288616) +++ soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/if_re_netmap.h Tue Jul 21 14:19:04 2015 (r288617) @@ -24,7 +24,7 @@ */ /* - * $FreeBSD$ + * $FreeBSD: head/sys/dev/netmap/if_re_netmap.h 234225 2012-04-13 15:33:12Z luigi $ * * netmap support for: re * @@ -159,8 +159,6 @@ } } - nm_txsync_finalize(kring); - return 0; } @@ -178,7 +176,7 @@ u_int nic_i; /* index into the NIC ring */ u_int n; u_int const lim = kring->nkr_num_slots - 1; - u_int const head = nm_rxsync_prologue(kring); + u_int const head = kring->rhead; int force_update = (flags & NAF_FORCE_READ) || kring->nr_kflags & NKR_PENDINTR; /* device-specific */ @@ -273,9 +271,6 @@ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); } - /* tell userspace that there might be new packets */ - nm_rxsync_finalize(kring); - return 0; ring_reset: Modified: soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/if_vtnet_netmap.h ============================================================================== --- soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/if_vtnet_netmap.h Tue Jul 21 14:10:22 2015 (r288616) +++ soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/if_vtnet_netmap.h Tue Jul 21 14:19:04 2015 (r288617) @@ -24,7 +24,7 @@ */ /* - * $FreeBSD$ + * $FreeBSD: head/sys/dev/netmap/if_vtnet_netmap.h 270097 2014-08-17 10:25:27Z luigi $ */ #include <net/netmap.h> @@ -32,6 +32,13 @@ #include <vm/vm.h> #include <vm/pmap.h> /* vtophys ? */ #include <dev/netmap/netmap_kern.h> +#ifdef WITH_PTNETMAP_GUEST +#include <dev/netmap/netmap_virt.h> +static int vtnet_ptnetmap_txsync(struct netmap_kring *kring, int flags); +#define VTNET_PTNETMAP_ON(_na) ((nm_netmap_on(_na)) && ((_na)->nm_txsync == vtnet_ptnetmap_txsync)) +#else /* !WITH_PTNETMAP_GUEST */ +#define VTNET_PTNETMAP_ON(_na) 0 +#endif /* WITH_PTNETMAP_GUEST */ #define SOFTC_T vtnet_softc @@ -214,9 +221,6 @@ virtqueue_postpone_intr(vq, VQ_POSTPONE_SHORT); } -//out: - nm_txsync_finalize(kring); - return 0; } @@ -278,7 +282,7 @@ // u_int nic_i; /* index into the NIC ring */ u_int n; u_int const lim = kring->nkr_num_slots - 1; - u_int const head = nm_rxsync_prologue(kring); + u_int const head = kring->rhead; int force_update = (flags & NAF_FORCE_READ) || kring->nr_kflags & NKR_PENDINTR; /* device-specific */ @@ -340,9 +344,6 @@ vtnet_rxq_enable_intr(rxq); } - /* tell userspace that there might be new packets. */ - nm_rxsync_finalize(kring); - ND("[C] h %d c %d t %d hwcur %d hwtail %d", ring->head, ring->cur, ring->tail, kring->nr_hwcur, kring->nr_hwtail); @@ -359,6 +360,9 @@ struct netmap_adapter* na = NA(ifp); unsigned int r; + /* if ptnetmap is enabled we must not init netmap buffers */ + if (VTNET_PTNETMAP_ON(na)) + return 1; if (!nm_native_on(na)) return 0; for (r = 0; r < na->num_rx_rings; r++) { @@ -409,6 +413,367 @@ return 0; } +#ifdef WITH_PTNETMAP_GUEST +/* ptnetmap virtio register BASE */ +#define PTNETMAP_VIRTIO_IO_BASE sizeof(struct virtio_net_config) + +#ifndef VIRTIO_NET_F_PTNETMAP +#define VIRTIO_NET_F_PTNETMAP 0x1000000 /* linux/qeum 24 */ +#endif /* VIRTIO_NET_F_PTNETMAP */ + +static void inline +vtnet_ptnetmap_iowrite4(device_t dev, uint32_t addr, uint32_t val) +{ + int i; + /* virtio_pci config_set use multiple iowrite8, we need to split the call and reverse the order */ + for (i = 3; i >= 0; i--) { + virtio_write_dev_config_1(dev, PTNETMAP_VIRTIO_IO_BASE + addr + i, *(((uint8_t *)&val) + i)); + } +} + +static uint32_t inline +vtnet_ptnetmap_ioread4(device_t dev, uint32_t addr) +{ + uint32_t val; + int i; + + for (i = 0; i <= 3; i++) { + *(((uint8_t *)&val) + i) = virtio_read_dev_config_1(dev, PTNETMAP_VIRTIO_IO_BASE + addr + i); + } + return val; +} + +static int +vtnet_ptnetmap_alloc_csb(struct SOFTC_T *sc) +{ + device_t dev = sc->vtnet_dev; + struct ifnet *ifp = sc->vtnet_ifp; + struct netmap_pt_guest_adapter* ptna = (struct netmap_pt_guest_adapter *)NA(ifp); + + vm_paddr_t csb_phyaddr; + + if (ptna->csb) + return 0; + + ptna->csb = contigmalloc(NET_PARAVIRT_CSB_SIZE, M_DEVBUF, M_NOWAIT | M_ZERO, + (size_t)0, -1UL, PAGE_SIZE, 0); + if (!ptna->csb) { + D("Communication Status Block allocation failed!"); + return ENOMEM; + } + + csb_phyaddr = vtophys(ptna->csb); + + ptna->csb->guest_csb_on = 1; + + /* Tell the device the CSB physical address. */ + vtnet_ptnetmap_iowrite4(dev, PTNETMAP_VIRTIO_IO_CSBBAH, (uint32_t)(csb_phyaddr >> 32)); + vtnet_ptnetmap_iowrite4(dev, PTNETMAP_VIRTIO_IO_CSBBAL, (uint32_t)(csb_phyaddr)); + + return 0; +} + +static void +vtnet_ptnetmap_free_csb(struct SOFTC_T *sc) +{ + device_t dev = sc->vtnet_dev; + struct ifnet *ifp = sc->vtnet_ifp; + struct netmap_pt_guest_adapter* ptna = (struct netmap_pt_guest_adapter *)NA(ifp); + + if (ptna->csb) { + /* CSB deallocation protocol. */ + vtnet_ptnetmap_iowrite4(dev, PTNETMAP_VIRTIO_IO_CSBBAH, 0x0ULL); + vtnet_ptnetmap_iowrite4(dev, PTNETMAP_VIRTIO_IO_CSBBAL, 0x0ULL); + + contigfree(ptna->csb, NET_PARAVIRT_CSB_SIZE, M_DEVBUF); + ptna->csb = NULL; + } +} + +static uint32_t vtnet_ptnetmap_ptctl(struct ifnet *, uint32_t); +static int +vtnet_ptnetmap_config(struct netmap_adapter *na, + u_int *txr, u_int *txd, u_int *rxr, u_int *rxd) +{ + struct netmap_pt_guest_adapter *ptna = (struct netmap_pt_guest_adapter *)na; + struct paravirt_csb *csb = ptna->csb; + int ret; + + if (csb == NULL) + return EINVAL; + + ret = vtnet_ptnetmap_ptctl(na->ifp, NET_PARAVIRT_PTCTL_CONFIG); + if (ret) + return ret; + + *txr = 1; //*txr = csb->num_tx_rings; + *rxr = 1; //*rxr = csb->num_rx_rings; + *txd = csb->num_tx_slots; + *rxd = csb->num_rx_slots; + + D("txr %u rxr %u txd %u rxd %u", + *txr, *rxr, *txd, *rxd); + return 0; +} + +static int +vtnet_ptnetmap_txsync(struct netmap_kring *kring, int flags) +{ + struct netmap_adapter *na = kring->na; + struct netmap_pt_guest_adapter *ptna = (struct netmap_pt_guest_adapter *)na; + struct ifnet *ifp = na->ifp; + u_int ring_nr = kring->ring_id; + + /* device-specific */ + struct SOFTC_T *sc = ifp->if_softc; + struct vtnet_txq *txq = &sc->vtnet_txqs[ring_nr]; + struct virtqueue *vq = txq->vtntx_vq; + struct paravirt_csb *csb = ptna->csb; + bool send_kick = false; + + /* Disable notifications */ + csb->guest_need_txkick = 0; + + /* + * First part: process new packets to send. + */ + kring->nr_hwcur = csb->tx_ring.hwcur; + ptnetmap_guest_write_kring_csb(&csb->tx_ring, kring->rcur, kring->rhead); + if (kring->rhead != kring->nr_hwcur) { + send_kick = true; + } + + /* Send kick to the host if it needs them */ + if ((send_kick && ACCESS_ONCE(csb->host_need_txkick)) || (flags & NAF_FORCE_RECLAIM)) { + csb->tx_ring.sync_flags = flags; + virtqueue_notify(vq); + } + + /* + * Second part: reclaim buffers for completed transmissions. + */ + if (flags & NAF_FORCE_RECLAIM || nm_kr_txempty(kring)) { + ptnetmap_guest_read_kring_csb(&csb->tx_ring, &kring->nr_hwcur, &kring->nr_hwtail, kring->nkr_num_slots); + } + + /* + * Ring full. The user thread will go to sleep and + * we need a notification (interrupt) from the NIC, + * whene there is free space. + */ + if (kring->rcur == kring->nr_hwtail) { + /* Reenable notifications. */ + csb->guest_need_txkick = 1; + /* Double check */ + ptnetmap_guest_read_kring_csb(&csb->tx_ring, &kring->nr_hwcur, &kring->nr_hwtail, kring->nkr_num_slots); + /* If there is new free space, disable notifications */ + if (kring->rcur != kring->nr_hwtail) { + csb->guest_need_txkick = 0; + } + } + + + ND(1,"TX - CSB: head:%u cur:%u hwtail:%u - KRING: head:%u cur:%u tail: %u", + csb->tx_ring.head, csb->tx_ring.cur, csb->tx_ring.hwtail, kring->rhead, kring->rcur, kring->nr_hwtail); + ND("TX - vq_index: %d", vq->index); + + return 0; +} + +static int +vtnet_ptnetmap_rxsync(struct netmap_kring *kring, int flags) +{ + struct netmap_adapter *na = kring->na; + struct netmap_pt_guest_adapter *ptna = (struct netmap_pt_guest_adapter *)na; + struct ifnet *ifp = na->ifp; + u_int ring_nr = kring->ring_id; + + /* device-specific */ + struct SOFTC_T *sc = ifp->if_softc; + struct vtnet_rxq *rxq = &sc->vtnet_rxqs[ring_nr]; + struct virtqueue *vq = rxq->vtnrx_vq; + struct paravirt_csb *csb = ptna->csb; + + int force_update = (flags & NAF_FORCE_READ) || kring->nr_kflags & NKR_PENDINTR; + uint32_t h_hwcur = kring->nr_hwcur, h_hwtail = kring->nr_hwtail; + + /* Disable notifications */ + csb->guest_need_rxkick = 0; + + ptnetmap_guest_read_kring_csb(&csb->rx_ring, &h_hwcur, &h_hwtail, kring->nkr_num_slots); + + /* + * First part: import newly received packets. + */ + if (netmap_no_pendintr || force_update) { + kring->nr_hwtail = h_hwtail; + kring->nr_kflags &= ~NKR_PENDINTR; + } + + /* + * Second part: skip past packets that userspace has released. + */ + kring->nr_hwcur = h_hwcur; + if (kring->rhead != kring->nr_hwcur) { + ptnetmap_guest_write_kring_csb(&csb->rx_ring, kring->rcur, kring->rhead); + /* Send kick to the host if it needs them */ + if (ACCESS_ONCE(csb->host_need_rxkick)) { + csb->rx_ring.sync_flags = flags; + virtqueue_notify(vq); + } + } + + /* + * Ring empty. The user thread will go to sleep and + * we need a notification (interrupt) from the NIC, + * whene there are new packets. + */ + if (kring->rcur == kring->nr_hwtail) { + /* Reenable notifications. */ + csb->guest_need_rxkick = 1; + /* Double check */ + ptnetmap_guest_read_kring_csb(&csb->rx_ring, &kring->nr_hwcur, &kring->nr_hwtail, kring->nkr_num_slots); + /* If there are new packets, disable notifications */ + if (kring->rcur != kring->nr_hwtail) { + csb->guest_need_rxkick = 0; + } + } + + ND("RX - CSB: head:%u cur:%u hwtail:%u - KRING: head:%u cur:%u", + csb->rx_ring.head, csb->rx_ring.cur, csb->rx_ring.hwtail, kring->rhead, kring->rcur); + ND("RX - vq_index: %d", vq->index); + + return 0; +} + +static int +vtnet_ptnetmap_reg(struct netmap_adapter *na, int onoff) +{ + struct netmap_pt_guest_adapter *ptna = (struct netmap_pt_guest_adapter *)na; + + /* device-specific */ + struct ifnet *ifp = na->ifp; + struct SOFTC_T *sc = ifp->if_softc; + struct paravirt_csb *csb = ptna->csb; + struct netmap_kring *kring; + int ret = 0; + + if (na == NULL) + return EINVAL; + + VTNET_CORE_LOCK(sc); + /* enable or disable flags and callbacks in na and ifp */ + if (onoff) { + int i; + nm_set_native_flags(na); + /* push fake-elem in the tx queues to enable interrupts */ + for (i = 0; i < sc->vtnet_max_vq_pairs; i++) { + struct vtnet_txq *txq = &sc->vtnet_txqs[i]; + struct mbuf *m0; + m0 = m_gethdr(M_NOWAIT, MT_DATA); + m0->m_len = 64; + + if (m0) { + ret = vtnet_txq_encap(txq, &m0); + } + } + ret = vtnet_ptnetmap_ptctl(na->ifp, NET_PARAVIRT_PTCTL_REGIF); + if (ret) { + //na->na_flags &= ~NAF_NETMAP_ON; + nm_clear_native_flags(na); + goto out; + } + /* + * Init ring and kring pointers + * After PARAVIRT_PTCTL_REGIF, the csb contains a snapshot of a + * host kring pointers. + * XXX This initialization is required, because we don't close the + * host port on UNREGIF. + */ + // Init rx ring + kring = na->rx_rings; + kring->rhead = kring->ring->head = csb->rx_ring.head; + kring->rcur = kring->ring->cur = csb->rx_ring.cur; + kring->nr_hwcur = csb->rx_ring.hwcur; + kring->nr_hwtail = kring->rtail = kring->ring->tail = csb->rx_ring.hwtail; + + // Init tx ring + kring = na->tx_rings; + kring->rhead = kring->ring->head = csb->tx_ring.head; + kring->rcur = kring->ring->cur = csb->tx_ring.cur; + kring->nr_hwcur = csb->tx_ring.hwcur; + kring->nr_hwtail = kring->rtail = kring->ring->tail = csb->tx_ring.hwtail; + } else { + ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); + //na->na_flags &= ~NAF_NETMAP_ON; + nm_clear_native_flags(na); + ret = vtnet_ptnetmap_ptctl(na->ifp, NET_PARAVIRT_PTCTL_UNREGIF); + vtnet_init_locked(sc); /* also enable intr */ + } +out: + VTNET_CORE_UNLOCK(sc); + return (ifp->if_drv_flags & IFF_DRV_RUNNING ? ret : 1); +} + +static int +vtnet_ptnetmap_bdg_attach(const char *bdg_name, struct netmap_adapter *na) +{ + return EOPNOTSUPP; +} + +static struct paravirt_csb * +vtnet_ptnetmap_getcsb(struct ifnet *ifp) +{ + struct netmap_pt_guest_adapter *ptna = (struct netmap_pt_guest_adapter *)NA(ifp); + + return ptna->csb; +} + +static uint32_t +vtnet_ptnetmap_ptctl(struct ifnet *ifp, uint32_t val) +{ + struct SOFTC_T *sc = ifp->if_softc; + device_t dev = sc->vtnet_dev; + uint32_t ret; + + D("PTCTL = %u", val); + vtnet_ptnetmap_iowrite4(dev, PTNETMAP_VIRTIO_IO_PTCTL, val); + ret = vtnet_ptnetmap_ioread4(dev, PTNETMAP_VIRTIO_IO_PTSTS); + D("PTSTS = %u", ret); + + return ret; +} + +static uint32_t +vtnet_ptnetmap_features(struct SOFTC_T *sc) +{ + device_t dev = sc->vtnet_dev; + uint32_t features; + /* tell the device the features we support */ + vtnet_ptnetmap_iowrite4(dev, PTNETMAP_VIRTIO_IO_PTFEAT, NET_PTN_FEATURES_BASE); + /* get back the acknowledged features */ + features = vtnet_ptnetmap_ioread4(dev, PTNETMAP_VIRTIO_IO_PTFEAT); + D("netmap passthrough: %s\n", + (features & NET_PTN_FEATURES_BASE) ? "base" : + "none"); + return features; +} + +static void +vtnet_ptnetmap_dtor(struct netmap_adapter *na) +{ + struct ifnet *ifp = na->ifp; + struct SOFTC_T *sc = ifp->if_softc; + + vtnet_ptnetmap_free_csb(sc); +} + +static struct netmap_pt_guest_ops vtnet_ptnetmap_ops = { + .nm_getcsb = vtnet_ptnetmap_getcsb, /* TODO: remove */ + .nm_ptctl = vtnet_ptnetmap_ptctl, +}; +#endif /* WITH_PTNETMAP_GUEST */ + static void vtnet_netmap_attach(struct SOFTC_T *sc) { @@ -425,6 +790,21 @@ na.nm_config = vtnet_netmap_config; na.num_tx_rings = na.num_rx_rings = sc->vtnet_max_vq_pairs; D("max rings %d", sc->vtnet_max_vq_pairs); +#ifdef WITH_PTNETMAP_GUEST + D("check ptnetmap support"); + if (virtio_with_feature(sc->vtnet_dev, VIRTIO_NET_F_PTNETMAP) && + (vtnet_ptnetmap_features(sc) & NET_PTN_FEATURES_BASE)) { + D("ptnetmap supported"); + na.nm_config = vtnet_ptnetmap_config; + na.nm_register = vtnet_ptnetmap_reg; + na.nm_txsync = vtnet_ptnetmap_txsync; + na.nm_rxsync = vtnet_ptnetmap_rxsync; + na.nm_dtor = vtnet_ptnetmap_dtor; + na.nm_bdg_attach = vtnet_ptnetmap_bdg_attach; /* XXX */ + netmap_pt_guest_attach(&na, &vtnet_ptnetmap_ops); + vtnet_ptnetmap_alloc_csb(sc); + } else +#endif /* WITH_PTNETMAP_GUEST */ netmap_attach(&na); D("virtio attached txq=%d, txd=%d rxq=%d, rxd=%d", Modified: soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/ixgbe_netmap.h ============================================================================== --- soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/ixgbe_netmap.h Tue Jul 21 14:10:22 2015 (r288616) +++ soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/ixgbe_netmap.h Tue Jul 21 14:19:04 2015 (r288617) @@ -24,7 +24,7 @@ */ /* - * $FreeBSD$ + * $FreeBSD: head/sys/dev/netmap/ixgbe_netmap.h 244514 2012-12-20 22:26:03Z luigi $ * * netmap support for: ixgbe * @@ -61,7 +61,8 @@ * count packets that might be missed due to lost interrupts. */ SYSCTL_DECL(_dev_netmap); -static int ix_rx_miss, ix_rx_miss_bufs, ix_crcstrip; +static int ix_rx_miss, ix_rx_miss_bufs; +int ix_crcstrip; SYSCTL_INT(_dev_netmap, OID_AUTO, ix_crcstrip, CTLFLAG_RW, &ix_crcstrip, 0, "strip CRC on rx frames"); SYSCTL_INT(_dev_netmap, OID_AUTO, ix_rx_miss, @@ -321,8 +322,6 @@ } } - nm_txsync_finalize(kring); - return 0; } @@ -350,7 +349,7 @@ u_int nic_i; /* index into the NIC ring */ u_int n; u_int const lim = kring->nkr_num_slots - 1; - u_int const head = nm_rxsync_prologue(kring); + u_int const head = kring->rhead; int force_update = (flags & NAF_FORCE_READ) || kring->nr_kflags & NKR_PENDINTR; /* device-specific */ @@ -457,9 +456,6 @@ IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDT(rxr->me), nic_i); } - /* tell userspace that there might be new packets */ - nm_rxsync_finalize(kring); - return 0; ring_reset: Modified: soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/netmap.c ============================================================================== --- soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/netmap.c Tue Jul 21 14:10:22 2015 (r288616) +++ soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/netmap.c Tue Jul 21 14:19:04 2015 (r288617) @@ -293,7 +293,7 @@ * kring->nm_sync() == DEVICE_netmap_rxsync() * 2) device interrupt handler * na->nm_notify() == netmap_notify() - * - tx from host stack + * - rx from host stack * concurrently: * 1) host stack * netmap_transmit() @@ -313,31 +313,113 @@ * * -= SYSTEM DEVICE WITH GENERIC SUPPORT =- * + * na == NA(ifp) == generic_netmap_adapter created in generic_netmap_attach() * - * - * -= VALE PORT =- - * - * - * - * -= NETMAP PIPE =- - * - * - * - * -= SYSTEM DEVICE WITH NATIVE SUPPORT, CONNECTED TO VALE, NO HOST RINGS =- - * - * - * - * -= SYSTEM DEVICE WITH NATIVE SUPPORT, CONNECTED TO VALE, WITH HOST RINGS =- - * - * - * - * -= SYSTEM DEVICE WITH GENERIC SUPPORT, CONNECTED TO VALE, NO HOST RINGS =- - * + * - tx from netmap userspace: + * concurrently: + * 1) ioctl(NIOCTXSYNC)/netmap_poll() in process context + * kring->nm_sync() == generic_netmap_txsync() + * linux: dev_queue_xmit() with NM_MAGIC_PRIORITY_TX + * generic_ndo_start_xmit() + * orig. dev. start_xmit + * FreeBSD: na->if_transmit() == orig. dev if_transmit + * 2) generic_mbuf_destructor() + * na->nm_notify() == netmap_notify() + * - rx from netmap userspace: + * 1) ioctl(NIOCRXSYNC)/netmap_poll() in process context + * kring->nm_sync() == generic_netmap_rxsync() + * mbq_safe_dequeue() + * 2) device driver + * generic_rx_handler() + * mbq_safe_enqueue() + * na->nm_notify() == netmap_notify() + * - rx from host stack: + * concurrently: *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201507211419.t6LEJ4Oa077713>