svn commit: r230023 - head/sys/dev/e1000

Luigi Rizzo luigi at FreeBSD.org
Thu Jan 12 17:28:00 UTC 2012


Author: luigi
Date: Thu Jan 12 17:28:00 2012
New Revision: 230023
URL: http://svn.freebsd.org/changeset/base/230023

Log:
  fix the initialization of the rings when netmap is used,
  to adapt it to the changes in  228387 .
  Now the code is similar to the one used in other drivers.
  Not applicable to stable/9 and stable/8

Modified:
  head/sys/dev/e1000/if_em.c

Modified: head/sys/dev/e1000/if_em.c
==============================================================================
--- head/sys/dev/e1000/if_em.c	Thu Jan 12 17:06:46 2012	(r230022)
+++ head/sys/dev/e1000/if_em.c	Thu Jan 12 17:28:00 2012	(r230023)
@@ -4019,6 +4019,10 @@ em_setup_receive_ring(struct rx_ring *rx
 	struct em_buffer	*rxbuf;
 	bus_dma_segment_t	seg[1];
 	int			rsize, nsegs, error;
+#ifdef DEV_NETMAP
+	struct netmap_adapter *na = NA(adapter->ifp);
+	struct netmap_slot *slot;
+#endif
 
 
 	/* Clear the ring contents */
@@ -4026,6 +4030,9 @@ em_setup_receive_ring(struct rx_ring *rx
 	rsize = roundup2(adapter->num_rx_desc *
 	    sizeof(struct e1000_rx_desc), EM_DBA_ALIGN);
 	bzero((void *)rxr->rx_base, rsize);
+#ifdef DEV_NETMAP
+	slot = netmap_reset(na, NR_RX, 0, 0);
+#endif
 
 	/*
 	** Free current RX buffer structs and their mbufs
@@ -4043,6 +4050,22 @@ em_setup_receive_ring(struct rx_ring *rx
 	/* Now replenish the mbufs */
         for (int j = 0; j != adapter->num_rx_desc; ++j) {
 		rxbuf = &rxr->rx_buffers[j];
+#ifdef DEV_NETMAP
+		if (slot) {
+			/* slot si is mapped to the j-th NIC-ring entry */
+			int si = j + na->rx_rings[0].nkr_hwofs;
+			uint64_t paddr;
+			void *addr;
+
+			if (si > na->num_rx_desc)
+				si -= na->num_rx_desc;
+			addr = PNMB(slot + si, &paddr);
+			netmap_load_map(rxr->rxtag, rxbuf->map, addr);
+			/* Update descriptor */
+			rxr->rx_base[j].buffer_addr = htole64(paddr);
+			continue;
+		}
+#endif /* DEV_NETMAP */
 		rxbuf->m_head = m_getjcl(M_DONTWAIT, MT_DATA,
 		    M_PKTHDR, adapter->rx_mbuf_sz);
 		if (rxbuf->m_head == NULL) {
@@ -4073,63 +4096,6 @@ em_setup_receive_ring(struct rx_ring *rx
 	bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map,
 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 
-#ifdef DEV_NETMAP
-    {
-	/*
-	 * This driver is slightly different from the standard:
-	 * it refills the rings in blocks of 8, so the while()
-	 * above completes any leftover work. Also, after if_init()
-	 * the ring starts at rxr->next_to_check instead of 0.
-	 *
-	 * Currently: we leave the mbufs allocated even in netmap
-	 * mode, and simply make the NIC ring point to the
-	 * correct buffer (netmap_buf or mbuf) depending on
-	 * the mode. To avoid mbuf leaks, when in netmap mode we
-	 * must make sure that next_to_refresh == next_to_check - 1
-	 * so that the above while() loop is never run on init.
-	 *
-	 * A better way would be to free the mbufs when entering
-	 * netmap mode, and set next_to_refresh/check in
-	 * a way that the mbufs are completely reallocated
-	 * when going back to standard mode.
-	 */
-	struct netmap_adapter *na = NA(adapter->ifp);
-	struct netmap_slot *slot = netmap_reset(na,
-		NR_RX, rxr->me, rxr->next_to_check);
-	int sj = slot ? na->rx_rings[rxr->me].nkr_hwofs : 0;
-
-	/* slot sj corresponds to entry j in the NIC ring */
-	if (sj < 0)
-		sj += adapter->num_rx_desc;
-
-	for (int j = 0; j != adapter->num_rx_desc; j++, sj++) {
-		rxbuf = &rxr->rx_buffers[j];
-		/* no mbuf and regular mode -> skip this entry */
-		if (rxbuf->m_head == NULL && !slot)
-			continue;
-		/* Handle wrap. Cannot use "na" here, could be NULL */
-		if (sj >= adapter->num_rx_desc)
-			sj -= adapter->num_rx_desc;
-		/* see comment, set slot addr and map */
-		if (slot) {
-			uint64_t paddr;
-			void *addr = PNMB(slot + sj, &paddr);
-			netmap_load_map(rxr->rxtag, rxbuf->map, addr);
-			/* Update descriptor */
-			rxr->rx_base[j].buffer_addr = htole64(paddr);
-		} else {
-			/* Get the memory mapping */
-			bus_dmamap_load_mbuf_sg(rxr->rxtag,
-			    rxbuf->map, rxbuf->m_head, seg,
-			    &nsegs, BUS_DMA_NOWAIT);
-			/* Update descriptor */
-			rxr->rx_base[j].buffer_addr = htole64(seg[0].ds_addr);
-		}
-		bus_dmamap_sync(rxr->rxtag, rxbuf->map, BUS_DMASYNC_PREREAD);
-	}
-    }
-#endif /* DEV_NETMAP */
-
 fail:
 	EM_RX_UNLOCK(rxr);
 	return (error);
@@ -4313,21 +4279,18 @@ em_initialize_receive_unit(struct adapte
 		E1000_WRITE_REG(hw, E1000_RDBAL(i), (u32)bus_addr);
 		/* Setup the Head and Tail Descriptor Pointers */
 		E1000_WRITE_REG(hw, E1000_RDH(i), 0);
-		E1000_WRITE_REG(hw, E1000_RDT(i), adapter->num_rx_desc - 1);
 #ifdef DEV_NETMAP
 		/*
 		 * an init() while a netmap client is active must
 		 * preserve the rx buffers passed to userspace.
 		 * In this driver it means we adjust RDT to
-		 * something different from next_to_refresh.
+		 * something different from na->num_rx_desc - 1.
 		 */
 		if (ifp->if_capenable & IFCAP_NETMAP) {
 			struct netmap_adapter *na = NA(adapter->ifp);
 			struct netmap_kring *kring = &na->rx_rings[i];
-			int t = rxr->next_to_refresh - kring->nr_hwavail;
+			int t = na->num_rx_desc - 1 - kring->nr_hwavail;
 
-			if (t < 0)
-				t += na->num_rx_desc;
 			E1000_WRITE_REG(hw, E1000_RDT(i), t);
 		} else
 #endif /* DEV_NETMAP */


More information about the svn-src-all mailing list