From owner-svn-soc-all@freebsd.org Wed May 11 15:23:27 2016 Return-Path: Delivered-To: svn-soc-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 83F83B36845 for ; Wed, 11 May 2016 15:23:27 +0000 (UTC) (envelope-from vincenzo@FreeBSD.org) Received: from socsvn.freebsd.org (socsvn.freebsd.org [IPv6:2001:1900:2254:206a::50:2]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 689471165 for ; Wed, 11 May 2016 15:23:27 +0000 (UTC) (envelope-from vincenzo@FreeBSD.org) Received: from socsvn.freebsd.org ([127.0.1.124]) by socsvn.freebsd.org (8.15.2/8.15.2) with ESMTP id u4BFNRaA022141 for ; Wed, 11 May 2016 15:23:27 GMT (envelope-from vincenzo@FreeBSD.org) Received: (from www@localhost) by socsvn.freebsd.org (8.15.2/8.15.2/Submit) id u4BFNO9Z019859 for svn-soc-all@FreeBSD.org; Wed, 11 May 2016 15:23:24 GMT (envelope-from vincenzo@FreeBSD.org) Date: Wed, 11 May 2016 15:23:24 GMT Message-Id: <201605111523.u4BFNO9Z019859@socsvn.freebsd.org> X-Authentication-Warning: socsvn.freebsd.org: www set sender to vincenzo@FreeBSD.org using -f From: vincenzo@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r302612 - in soc2016/vincenzo/head/sys: dev/netmap modules/netmap net MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-soc-all@freebsd.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: SVN commit messages for the entire Summer of Code repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 11 May 2016 15:23:27 -0000 Author: vincenzo Date: Wed May 11 15:23:23 2016 New Revision: 302612 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=302612 Log: Update netmap sources to the github ones Added: soc2016/vincenzo/head/sys/dev/netmap/if_nfe_netmap.h soc2016/vincenzo/head/sys/dev/netmap/netmap_virt.h soc2016/vincenzo/head/sys/dev/netmap/ptnetmap.c Modified: soc2016/vincenzo/head/sys/dev/netmap/if_em_netmap.h soc2016/vincenzo/head/sys/dev/netmap/if_ixl_netmap.h soc2016/vincenzo/head/sys/dev/netmap/if_lem_netmap.h soc2016/vincenzo/head/sys/dev/netmap/if_vtnet_netmap.h soc2016/vincenzo/head/sys/dev/netmap/ixgbe_netmap.h soc2016/vincenzo/head/sys/dev/netmap/netmap.c soc2016/vincenzo/head/sys/dev/netmap/netmap_freebsd.c soc2016/vincenzo/head/sys/dev/netmap/netmap_generic.c soc2016/vincenzo/head/sys/dev/netmap/netmap_kern.h soc2016/vincenzo/head/sys/dev/netmap/netmap_mbq.c soc2016/vincenzo/head/sys/dev/netmap/netmap_mbq.h soc2016/vincenzo/head/sys/dev/netmap/netmap_mem2.c soc2016/vincenzo/head/sys/dev/netmap/netmap_mem2.h soc2016/vincenzo/head/sys/dev/netmap/netmap_monitor.c soc2016/vincenzo/head/sys/dev/netmap/netmap_offloadings.c soc2016/vincenzo/head/sys/dev/netmap/netmap_pipe.c soc2016/vincenzo/head/sys/dev/netmap/netmap_vale.c soc2016/vincenzo/head/sys/modules/netmap/Makefile soc2016/vincenzo/head/sys/net/netmap.h soc2016/vincenzo/head/sys/net/netmap_user.h Modified: soc2016/vincenzo/head/sys/dev/netmap/if_em_netmap.h ============================================================================== --- soc2016/vincenzo/head/sys/dev/netmap/if_em_netmap.h Wed May 11 14:59:54 2016 (r302611) +++ soc2016/vincenzo/head/sys/dev/netmap/if_em_netmap.h Wed May 11 15:23:23 2016 (r302612) @@ -148,7 +148,7 @@ /* device-specific */ struct e1000_tx_desc *curr = &txr->tx_base[nic_i]; - struct em_txbuffer *txbuf = &txr->tx_buffers[nic_i]; + struct em_buffer *txbuf = &txr->tx_buffers[nic_i]; int flags = (slot->flags & NS_REPORT || nic_i == 0 || nic_i == report_frequency) ? E1000_TXD_CMD_RS : 0; @@ -239,12 +239,12 @@ nm_i = netmap_idx_n2k(kring, nic_i); for (n = 0; ; n++) { // XXX no need to count - union e1000_rx_desc_extended *curr = &rxr->rx_base[nic_i]; - uint32_t staterr = le32toh(curr->wb.upper.status_error); + struct e1000_rx_desc *curr = &rxr->rx_base[nic_i]; + uint32_t staterr = le32toh(curr->status); if ((staterr & E1000_RXD_STAT_DD) == 0) break; - ring->slot[nm_i].len = le16toh(curr->wb.upper.length); + ring->slot[nm_i].len = le16toh(curr->length); ring->slot[nm_i].flags = slot_flags; bus_dmamap_sync(rxr->rxtag, rxr->rx_buffers[nic_i].map, BUS_DMASYNC_POSTREAD); @@ -271,19 +271,19 @@ uint64_t paddr; void *addr = PNMB(na, slot, &paddr); - union e1000_rx_desc_extended *curr = &rxr->rx_base[nic_i]; - struct em_rxbuffer *rxbuf = &rxr->rx_buffers[nic_i]; + struct e1000_rx_desc *curr = &rxr->rx_base[nic_i]; + struct em_buffer *rxbuf = &rxr->rx_buffers[nic_i]; if (addr == NETMAP_BUF_BASE(na)) /* bad buf */ goto ring_reset; if (slot->flags & NS_BUF_CHANGED) { /* buffer has changed, reload map */ - curr->read.buffer_addr = htole64(paddr); + curr->buffer_addr = htole64(paddr); netmap_reload_map(na, rxr->rxtag, rxbuf->map, addr); slot->flags &= ~NS_BUF_CHANGED; } - curr->wb.upper.status_error = 0; + curr->status = 0; bus_dmamap_sync(rxr->rxtag, rxbuf->map, BUS_DMASYNC_PREREAD); nm_i = nm_next(nm_i, lim); Modified: soc2016/vincenzo/head/sys/dev/netmap/if_ixl_netmap.h ============================================================================== --- soc2016/vincenzo/head/sys/dev/netmap/if_ixl_netmap.h Wed May 11 14:59:54 2016 (r302611) +++ soc2016/vincenzo/head/sys/dev/netmap/if_ixl_netmap.h Wed May 11 15:23:23 2016 (r302612) @@ -59,7 +59,7 @@ /* * device-specific sysctl variables: * - * ixl_crcstrip: 0: keep CRC in rx frames (default), 1: strip it. + * ixl_crcstrip: 0: NIC keeps CRC in rx frames (default), 1: NIC strips it. * During regular operations the CRC is stripped, but on some * hardware reception of frames not multiple of 64 is slower, * so using crcstrip=0 helps in benchmarks. @@ -74,7 +74,7 @@ int ixl_rx_miss, ixl_rx_miss_bufs, ixl_crcstrip = 1; #if 0 SYSCTL_INT(_dev_netmap, OID_AUTO, ixl_crcstrip, - CTLFLAG_RW, &ixl_crcstrip, 1, "strip CRC on rx frames"); + CTLFLAG_RW, &ixl_crcstrip, 1, "NIC strips CRC on rx frames"); #endif SYSCTL_INT(_dev_netmap, OID_AUTO, ixl_rx_miss, CTLFLAG_RW, &ixl_rx_miss, 0, "potentially missed rx intr"); Modified: soc2016/vincenzo/head/sys/dev/netmap/if_lem_netmap.h ============================================================================== --- soc2016/vincenzo/head/sys/dev/netmap/if_lem_netmap.h Wed May 11 14:59:54 2016 (r302611) +++ soc2016/vincenzo/head/sys/dev/netmap/if_lem_netmap.h Wed May 11 15:23:23 2016 (r302612) @@ -38,6 +38,10 @@ #include #include /* vtophys ? */ #include +#ifdef WITH_PTNETMAP_GUEST +#include +#endif +#include extern int netmap_adaptive_io; @@ -80,6 +84,20 @@ return (ifp->if_drv_flags & IFF_DRV_RUNNING ? 0 : 1); } +static void +lem_netmap_intr(struct netmap_adapter *na, int onoff) +{ + struct ifnet *ifp = na->ifp; + struct adapter *adapter = ifp->if_softc; + + EM_CORE_LOCK(adapter); + if (onoff) { + lem_enable_intr(adapter); + } else { + lem_disable_intr(adapter); + } + EM_CORE_UNLOCK(adapter); +} /* * Reconcile kernel and user view of the transmit ring. @@ -470,6 +488,176 @@ return netmap_ring_reinit(kring); } +#if defined (NIC_PTNETMAP) && defined (WITH_PTNETMAP_GUEST) +/* + * ptnetmap support for: lem (FreeBSD version) + * + * For details on ptnetmap support please see if_vtnet_netmap.h + */ +static uint32_t lem_ptnetmap_ptctl(struct ifnet *, uint32_t); + +/* Returns device configuration from the CSB */ +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_ptnetmap_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; +} + +/* Reconcile host and guest view of the transmit ring. */ +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; + bool notify; + + notify = netmap_pt_guest_txsync(&adapter->csb->tx_ring, kring, flags); + if (notify) + E1000_WRITE_REG(&adapter->hw, E1000_TDT(0), 0); + + return 0; +} + +/* Reconcile host and guest view of the receive ring. */ +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; + bool notify; + + notify = netmap_pt_guest_rxsync(&adapter->csb->rx_ring, kring, flags); + if (notify) + E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), 0); + + return 0; +} + +/* Register/unregister. We are already under netmap lock. */ +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_ptnetmap_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_ptnetmap_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; +} + +/* Send command to the host through PTCTL register. */ +static uint32_t +lem_ptnetmap_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; +} + +/* Features negotiation with the host through PTFEAT */ +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, "ptnetmap support: %s\n", + (features & NET_PTN_FEATURES_BASE) ? "base" : + "none"); + return features; +} + +static void +lem_ptnetmap_dtor(struct netmap_adapter *na) +{ + netmap_mem_pt_guest_ifp_del(na->nm_mem, na->ifp); +} + +/* XXX: these warning affect proper kernel compilation +#elif defined (NIC_PTNETMAP) +#warning "if_lem supports ptnetmap but netmap does not support it" +#warning "(configure netmap with ptnetmap support)" +#elif defined (WITH_PTNETMAP_GUEST) +#warning "netmap supports ptnetmap but e1000 does not support it" +#warning "(configure if_lem with ptnetmap support)" +*/ +#endif /* NIC_PTNETMAP && WITH_PTNETMAP_GUEST */ static void lem_netmap_attach(struct adapter *adapter) @@ -486,7 +674,34 @@ na.nm_rxsync = lem_netmap_rxsync; na.nm_register = lem_netmap_reg; na.num_tx_rings = na.num_rx_rings = 1; - netmap_attach(&na); + na.nm_intr = lem_netmap_intr; +#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)) { + int err; + + 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 */ + na.nm_dtor = lem_ptnetmap_dtor; + + /* Ask the device to fill in some configuration fields. Here we + * just need nifp_offset. */ + err = lem_ptnetmap_ptctl(na.ifp, NET_PARAVIRT_PTCTL_CONFIG); + if (err) { + D("Failed to get nifp_offset from passthrough device"); + return; + } + + netmap_pt_guest_attach(&na, adapter->csb, + adapter->csb->nifp_offset, + lem_ptnetmap_ptctl); + } else +#endif /* NIC_PTNETMAP && defined WITH_PTNETMAP_GUEST */ + netmap_attach(&na); } /* end of file */ Added: soc2016/vincenzo/head/sys/dev/netmap/if_nfe_netmap.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ soc2016/vincenzo/head/sys/dev/netmap/if_nfe_netmap.h Wed May 11 15:23:23 2016 (r302612) @@ -0,0 +1,384 @@ +/* + * Copyright (C) 2011-2014 Luigi Rizzo. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $FreeBSD: head/sys/dev/netmap/if_em_netmap.h 231881 2012-02-17 14:09:04Z luigi $ + * + * netmap support for: nfe XXX not yet tested. + * + * For more details on netmap support please see ixgbe_netmap.h + */ + + +#include +#include +#include +#include + +#include + + +static int +nfe_netmap_init_buffers(struct nfe_softc *sc) +{ + struct netmap_adapter *na = NA(sc->nfe_ifp); + struct netmap_slot *slot; + int i, l, n, max_avail; + struct nfe_desc32 *desc32 = NULL; + struct nfe_desc64 *desc64 = NULL; + void *addr; + uint64_t paddr; + + slot = netmap_reset(na, NR_TX, 0, 0); + if (!slot) + return 0; // not in native mode + // XXX init the tx ring + n = NFE_TX_RING_COUNT; + for (i = 0; i < n; i++) { + l = netmap_idx_n2k(&na->tx_rings[0], i); + addr = PNMB(na, slot + l, &paddr); + netmap_reload_map(sc->txq.tx_data_tag, + sc->txq.data[l].tx_data_map, addr); + slot[l].flags = 0; + if (sc->nfe_flags & NFE_40BIT_ADDR) { + desc64 = &sc->txq.desc64[l]; + desc64->physaddr[0] = htole32(NFE_ADDR_HI(paddr)); + desc64->physaddr[1] = htole32(NFE_ADDR_LO(paddr)); + desc64->vtag = 0; + desc64->length = htole16(0); + desc64->flags = htole16(0); + } else { + desc32 = &sc->txq.desc32[l]; + desc32->physaddr = htole32(NFE_ADDR_LO(paddr)); + desc32->length = htole16(0); + desc32->flags = htole16(0); + } + } + + slot = netmap_reset(na, NR_RX, 0, 0); + // XXX init the rx ring + /* + * preserve buffers still owned by the driver (and keep one empty). + */ + n = NFE_RX_RING_COUNT; + max_avail = n - 1 - nm_kr_rxspace(&na->rx_rings[0]); + for (i = 0; i < n; i++) { + uint16_t flags; + l = netmap_idx_n2k(&na->rx_rings[0], i); + addr = PNMB(na, slot + l, &paddr); + flags = (i < max_avail) ? NFE_RX_READY : 0; + if (sc->nfe_flags & NFE_40BIT_ADDR) { + desc64 = &sc->rxq.desc64[l]; + desc64->physaddr[0] = htole32(NFE_ADDR_HI(paddr)); + desc64->physaddr[1] = htole32(NFE_ADDR_LO(paddr)); + desc64->vtag = 0; + desc64->length = htole16(NETMAP_BUF_SIZE); + desc64->flags = htole16(NFE_RX_READY); + } else { + desc32 = &sc->rxq.desc32[l]; + desc32->physaddr = htole32(NFE_ADDR_LO(paddr)); + desc32->length = htole16(NETMAP_BUF_SIZE); + desc32->flags = htole16(NFE_RX_READY); + } + + netmap_reload_map(sc->rxq.rx_data_tag, + sc->rxq.data[l].rx_data_map, addr); + bus_dmamap_sync(sc->rxq.rx_data_tag, + sc->rxq.data[l].rx_data_map, BUS_DMASYNC_PREREAD); + } + + return 1; +} + + +/* + * Register/unregister. We are already under netmap lock. + */ +static int +nfe_netmap_reg(struct netmap_adapter *na, int onoff) +{ + struct ifnet *ifp = na->ifp; + struct nfe_softc *sc = ifp->if_softc; + + NFE_LOCK(sc); + nfe_stop(ifp); /* also clear IFF_DRV_RUNNING */ + if (onoff) { + nm_set_native_flags(na); + } else { + nm_clear_native_flags(na); + } + nfe_init_locked(sc); /* also enable intr */ + NFE_UNLOCK(sc); + return (0); +} + + +/* + * Reconcile kernel and user view of the transmit ring. + */ +static int +nfe_netmap_txsync(struct netmap_kring *kring, int flags) +{ + struct netmap_adapter *na = kring->na; + struct ifnet *ifp = na->ifp; + struct netmap_ring *ring = kring->ring; + u_int nm_i; /* index into the netmap ring */ + 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 = kring->rhead; + /* generate an interrupt approximately every half ring */ + u_int report_frequency = kring->nkr_num_slots >> 1; + + /* device-specific */ + struct nfe_softc *sc = ifp->if_softc; + struct nfe_desc32 *desc32 = NULL; + struct nfe_desc64 *desc64 = NULL; + + bus_dmamap_sync(sc->txq.tx_desc_tag, sc->txq.tx_desc_map, + BUS_DMASYNC_POSTREAD); + + /* + * First part: process new packets to send. + */ + + nm_i = kring->nr_hwcur; + if (nm_i != head) { /* we have new packets to send */ + nic_i = netmap_idx_k2n(kring, nm_i); + for (n = 0; nm_i != head; n++) { + /* slot is the current slot in the netmap ring */ + struct netmap_slot *slot = &ring->slot[nm_i]; + u_int len = slot->len; + uint64_t paddr; + void *addr = PNMB(na, slot, &paddr); + + NM_CHECK_ADDR_LEN(addr, len); + + if (slot->flags & NS_BUF_CHANGED) { + /* buffer has changed, reload map */ + netmap_reload_map(sc->txq.tx_data_tag, + sc->txq.data[l].tx_data_map, addr); + } + slot->flags &= ~(NS_REPORT | NS_BUF_CHANGED); + + if (sc->nfe_flags & NFE_40BIT_ADDR) { + desc64 = &sc->txq.desc64[l]; + desc64->physaddr[0] = htole32(NFE_ADDR_HI(paddr)); + desc64->physaddr[1] = htole32(NFE_ADDR_LO(paddr)); + desc64->vtag = 0; + desc64->length = htole16(len - 1); + desc64->flags = + htole16(NFE_TX_VALID | NFE_TX_LASTFRAG_V2); + } else { + desc32 = &sc->txq.desc32[l]; + desc32->physaddr = htole32(NFE_ADDR_LO(paddr)); + desc32->length = htole16(len - 1); + desc32->flags = + htole16(NFE_TX_VALID | NFE_TX_LASTFRAG_V1); + } + + bus_dmamap_sync(sc->txq.tx_data_tag, + sc->txq.data[l].tx_data_map, BUS_DMASYNC_PREWRITE); + nm_i = nm_next(nm_i, lim); + nic_i = nm_next(nic_i, lim); + } + kring->nr_hwcur = head; + sc->txq.cur = nic_i; + + bus_dmamap_sync(sc->txq.tx_desc_tag, sc->txq.tx_desc_map, + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); + + /* XXX something missing ? where is the last pkt marker ? */ + NFE_WRITE(sc, NFE_RXTX_CTL, NFE_RXTX_KICKTX | sc->rxtxctl); + } + + /* + * Second part: reclaim buffers for completed transmissions. + */ + if (flags & NAF_FORCE_RECLAIM || nm_kr_txempty(kring)) { + u_int nic_cur = sc->txq.cur; + nic_i = sc->txq.next; + for (n = 0; nic_i != nic_cur; n++, NFE_INC(nic_i, NFE_TX_RING_COUNT)) { + uint16_t flags; + if (sc->nfe_flags & NFE_40BIT_ADDR) { + desc64 = &sc->txq.desc64[l]; + flags = le16toh(desc64->flags); + } else { + desc32 = &sc->txq.desc32[l]; + flags = le16toh(desc32->flags); + } + if (flags & NFE_TX_VALID) + break; + } + if (n > 0) { + sc->txq.next = nic_i; + kring->nr_hwtail = nm_prev(netmap_idx_n2k(kring, nic_i), lim); + } + } + + + return 0; +} + + +/* + * Reconcile kernel and user view of the receive ring. + */ +static int +nfe_netmap_rxsync(struct netmap_kring *kring, int flags) +{ + struct netmap_adapter *na = kring->na; + struct ifnet *ifp = na->ifp; + struct netmap_ring *ring = kring->ring; + u_int nm_i; /* index into the netmap ring */ + 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 = kring->rhead; + int force_update = (flags & NAF_FORCE_READ) || kring->nr_kflags & NKR_PENDINTR; + + /* device-specific */ + struct nfe_softc *sc = ifp->if_softc; + struct nfe_desc32 *desc32; + struct nfe_desc64 *desc64; + + if (head > lim) + return netmap_ring_reinit(kring); + + bus_dmamap_sync(sc->rxq.rx_desc_tag, sc->rxq.rx_desc_map, + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); + + /* + * First part: import newly received packets. + */ + if (netmap_no_pendintr || force_update) { + uint16_t flags, len; + uint16_t slot_flags = kring->nkr_slot_flags; + + nic_i = sc->rxq.cur; + nm_i = netmap_idx_n2k(kring, nic_i); + for (n = 0; ; n++) { + if (sc->nfe_flags & NFE_40BIT_ADDR) { + desc64 = &sc->rxq.desc64[sc->rxq.cur]; + flags = le16toh(desc64->flags); + len = le16toh(desc64->length) & NFE_RX_LEN_MASK; + } else { + desc32 = &sc->rxq.desc32[sc->rxq.cur]; + flags = le16toh(desc32->flags); + len = le16toh(desc32->length) & NFE_RX_LEN_MASK; + } + + if (flags & NFE_RX_READY) + break; + + ring->slot[nm_i].len = len; + ring->slot[nm_i].flags = slot_flags; + bus_dmamap_sync(sc->rxq.rx_data_tag, + sc->rxq.data[nic_i].rx_data_map, + BUS_DMASYNC_POSTREAD); + nm_i = nm_next(nm_i, lim); + nic_i = nm_next(nic_i, lim); + } + if (n) { /* update the state variables */ + sc->rxq.cur = nic_i; + kring->nr_hwtail = nm_i; + } + kring->nr_kflags &= ~NKR_PENDINTR; + } + + /* + * Second part: skip past packets that userspace has released. + */ + nm_i = kring->nr_hwcur; + if (nm_i != head) { + nic_i = netmap_idx_k2n(kring, nm_i); + for (n = 0; nm_i != head; n++) { + struct netmap_slot *slot = &ring->slot[nm_i]; + uint64_t paddr; + void *addr = PNMB(na, slot, &paddr); + + if (addr == netmap_buffer_base) /* bad buf */ + goto ring_reset; + + if (slot->flags & NS_BUF_CHANGED) { + /* buffer has changed, reload map */ + netmap_reload_map(sc->rxq.rx_data_tag, + sc->rxq.data[l].rx_data_map, addr); + slot->flags &= ~NS_BUF_CHANGED; + } + if (sc->nfe_flags & NFE_40BIT_ADDR) { + desc64 = &sc->rxq.desc64[nic_i]; + desc64->physaddr[0] = + htole32(NFE_ADDR_HI(paddr)); + desc64->physaddr[1] = + htole32(NFE_ADDR_LO(paddr)); + desc64->length = htole16(NETMAP_BUF_SIZE); + desc64->flags = htole16(NFE_RX_READY); + } else { + desc32 = &sc->rxq.desc32[nic_i]; + desc32->physaddr = + htole32(NFE_ADDR_LO(paddr)); + desc32->length = htole16(NETMAP_BUF_SIZE); + desc32->flags = htole16(NFE_RX_READY); + } + + bus_dmamap_sync(sc->rxq.rx_data_tag, + sc->rxq.data[nic_i].rx_data_map, + BUS_DMASYNC_PREREAD); + nm_i = nm_next(nm_i, lim); + nic_i = nm_next(nic_i, lim); + } + kring->nr_hwcur = head; + bus_dmamap_sync(sc->rxq.rx_desc_tag, sc->rxq.rx_desc_map, + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); + } + + + return 0; + +ring_reset: + return netmap_ring_reinit(kring); +} + + +static void +nfe_netmap_attach(struct nfe_softc *sc) +{ + struct netmap_adapter na; + + bzero(&na, sizeof(na)); + + na.ifp = sc->nfe_ifp; + na.na_flags = NAF_BDG_MAYSLEEP; + na.num_tx_desc = NFE_TX_RING_COUNT; + na.num_rx_desc = NFE_RX_RING_COUNT; + na.nm_txsync = nfe_netmap_txsync; + na.nm_rxsync = nfe_netmap_rxsync; + na.nm_register = nfe_netmap_reg; + na.num_tx_rings = na.num_rx_rings = 1; + netmap_attach(&na, 1); +} + +/* end of file */ Modified: soc2016/vincenzo/head/sys/dev/netmap/if_vtnet_netmap.h ============================================================================== --- soc2016/vincenzo/head/sys/dev/netmap/if_vtnet_netmap.h Wed May 11 14:59:54 2016 (r302611) +++ soc2016/vincenzo/head/sys/dev/netmap/if_vtnet_netmap.h Wed May 11 15:23:23 2016 (r302612) @@ -32,6 +32,15 @@ #include #include /* vtophys ? */ #include +#ifdef WITH_PTNETMAP_GUEST +#include +#include +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 @@ -353,6 +362,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++) { @@ -403,6 +415,331 @@ return 0; } +#ifdef WITH_PTNETMAP_GUEST +/* + * ptnetmap support for: virtio-net (FreeBSD version) + * + * this part od this file is meant to be a reference on how to implement + * ptnetmap support for a network driver. + * this file contains code but only static or inline functions used + * by a single driver. + */ + +/* + * virtio-specific macro and fucntions + */ +/* ptnetmap virtio register BASE */ +#define PTNETMAP_VIRTIO_IO_BASE sizeof(struct virtio_net_config) +#ifndef VIRTIO_NET_F_PTNETMAP +#define VIRTIO_NET_F_PTNETMAP 0x2000000 /* linux/qeum 25 */ +#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; +} + +/* + * CSB (Communication Status Block) allocation. + * CSB is the shared memory used by the netmap instance running in the guest + * and the ptnetmap kthreads in the host. + * The CSBBAH/CSBBAL registers must be added to the virtio-net device. + * + * Only called after netmap_pt_guest_attach(). + */ +static struct paravirt_csb * +vtnet_ptnetmap_alloc_csb(struct SOFTC_T *sc) +{ + device_t dev = sc->vtnet_dev; + struct paravirt_csb *csb; + + vm_paddr_t csb_phyaddr; + + csb = contigmalloc(NET_PARAVIRT_CSB_SIZE, M_DEVBUF, + M_NOWAIT | M_ZERO, (size_t)0, -1UL, PAGE_SIZE, 0); + if (!csb) { + D("Communication Status Block allocation failed!"); + return NULL; + } + + csb_phyaddr = vtophys(csb); + + 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 csb; +} + +/* + * CSB (Communication Status Block) deallocation. + */ +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); + +/* + * Returns device configuration from the CSB, after sending the PTCTL_CONFIG + * command to the host (hypervisor virtio fronted). + * The host reads the configuration from the netmap port (opened in the host) + * and it stores the values in the CSB. + */ +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; + + ND("txr %u rxr %u txd %u rxd %u", + *txr, *rxr, *txd, *rxd); + return 0; +} + +/* + * Reconcile host and guest view of the transmit ring. + * Use generic netmap_pt_guest_txsync(). + * Only the notification to the host is device-specific. + */ +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 paravirt_csb *csb = ptna->csb; + struct ifnet *ifp = na->ifp; + u_int ring_nr = kring->ring_id; + struct SOFTC_T *sc = ifp->if_softc; + struct virtqueue *vq = sc->vtnet_txqs[ring_nr].vtntx_vq; + bool notify; + + notify = netmap_pt_guest_txsync(&csb->tx_ring, kring, flags); + if (notify) + virtqueue_notify(vq); + + ND("TX - vq_index: %d", vq->index); + + return 0; +} + +/* + * Reconcile host and guest view of the receive ring. + * Use generic netmap_pt_guest_rxsync(). + * Only the notification to the host is device-specific. + */ +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 paravirt_csb *csb = ptna->csb; + struct ifnet *ifp = na->ifp; + u_int ring_nr = kring->ring_id; + struct SOFTC_T *sc = ifp->if_softc; + struct virtqueue *vq = sc->vtnet_rxqs[ring_nr].vtnrx_vq; + bool notify; + + notify = netmap_pt_guest_rxsync(&csb->rx_ring, kring, flags); + if (notify) + virtqueue_notify(vq); + + ND("RX - vq_index: %d", vq->index); + + return 0; +} + +/* + * Register/unregister. We are already under netmap lock. + * Only called on the first register or the last unregister. + */ +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: *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***