svn commit: r354344 - head/sys/net

Eric Joyner erj at FreeBSD.org
Mon Nov 4 23:06:58 UTC 2019


Author: erj
Date: Mon Nov  4 23:06:57 2019
New Revision: 354344
URL: https://svnweb.freebsd.org/changeset/base/354344

Log:
  iflib: properly release memory allocated for DMA
  
  DMA memory allocations using the bus_dma.h interface are not properly
  released in all cases for both Tx and Rx. This causes ~448 bytes of
  M_DEVBUF allocations to be leaked.
  
  First, the DMA maps for Rx are not properly destroyed. A slight attempt
  is made in iflib_fl_bufs_free to destroy the maps if we're detaching.
  However, this function may not be reliably called during detach. Indeed,
  there is a comment "asking" if this should be moved out.
  
  Fix this by moving the bus_dmamap_destroy call into iflib_rx_sds_free,
  where we already sync and unload the DMA.
  
  Second, the DMA tag associated with the ifr_ifdi descriptor DMA is not
  released properly anywhere. Add a call to iflib_dma_free in
  iflib_rx_structures_free.
  
  Third, use of NULL as a canary value on the map pointer returned by
  bus_dmamap_create is not valid. On some platforms, notably x86, this
  value may be NULL. In this case, we fail to properly release the related
  resources.
  
  Remove the NULL checks on map values in both iflib_fl_bufs_free and
  iflib_txsd_destroy.
  
  With all of these fixes applied, the leaks to M_DEVBUF are squelched,
  and iflib drivers now seem to properly cleanup when detaching.
  
  Signed-off-by: Jacob Keller <jacob.e.keller at intel.com>
  
  Submitted by:	Jacob Keller <jacob.e.keller at intel.com>
  Reviewed by:	erj@, gallatin@
  MFC after:	1 week
  Sponsored by:	Intel Corporation
  Differential Revision:	https://reviews.freebsd.org/D22203

Modified:
  head/sys/net/iflib.c

Modified: head/sys/net/iflib.c
==============================================================================
--- head/sys/net/iflib.c	Mon Nov  4 22:57:36 2019	(r354343)
+++ head/sys/net/iflib.c	Mon Nov  4 23:06:57 2019	(r354344)
@@ -1696,20 +1696,16 @@ iflib_txsd_destroy(if_ctx_t ctx, iflib_txq_t txq, int 
 {
 	bus_dmamap_t map;
 
-	map = NULL;
-	if (txq->ift_sds.ifsd_map != NULL)
+	if (txq->ift_sds.ifsd_map != NULL) {
 		map = txq->ift_sds.ifsd_map[i];
-	if (map != NULL) {
 		bus_dmamap_sync(txq->ift_buf_tag, map, BUS_DMASYNC_POSTWRITE);
 		bus_dmamap_unload(txq->ift_buf_tag, map);
 		bus_dmamap_destroy(txq->ift_buf_tag, map);
 		txq->ift_sds.ifsd_map[i] = NULL;
 	}
 
-	map = NULL;
-	if (txq->ift_sds.ifsd_tso_map != NULL)
+	if (txq->ift_sds.ifsd_tso_map != NULL) {
 		map = txq->ift_sds.ifsd_tso_map[i];
-	if (map != NULL) {
 		bus_dmamap_sync(txq->ift_tso_buf_tag, map,
 		    BUS_DMASYNC_POSTWRITE);
 		bus_dmamap_unload(txq->ift_tso_buf_tag, map);
@@ -2120,9 +2116,6 @@ iflib_fl_bufs_free(iflib_fl_t fl)
 			bus_dmamap_unload(fl->ifl_buf_tag, sd_map);
 			if (*sd_cl != NULL)
 				uma_zfree(fl->ifl_zone, *sd_cl);
-			// XXX: Should this get moved out?
-			if (iflib_in_detach(fl->ifl_rxq->ifr_ctx))
-				bus_dmamap_destroy(fl->ifl_buf_tag, sd_map);
 			if (*sd_m != NULL) {
 				m_init(*sd_m, M_NOWAIT, MT_DATA, 0);
 				uma_zfree(zone_mbuf, *sd_m);
@@ -2210,9 +2203,6 @@ iflib_rx_sds_free(iflib_rxq_t rxq)
 			if (fl->ifl_buf_tag != NULL) {
 				if (fl->ifl_sds.ifsd_map != NULL) {
 					for (j = 0; j < fl->ifl_size; j++) {
-						if (fl->ifl_sds.ifsd_map[j] ==
-						    NULL)
-							continue;
 						bus_dmamap_sync(
 						    fl->ifl_buf_tag,
 						    fl->ifl_sds.ifsd_map[j],
@@ -2220,6 +2210,9 @@ iflib_rx_sds_free(iflib_rxq_t rxq)
 						bus_dmamap_unload(
 						    fl->ifl_buf_tag,
 						    fl->ifl_sds.ifsd_map[j]);
+						bus_dmamap_destroy(
+						    fl->ifl_buf_tag,
+						    fl->ifl_sds.ifsd_map[j]);
 					}
 				}
 				bus_dma_tag_destroy(fl->ifl_buf_tag);
@@ -5735,9 +5728,12 @@ static void
 iflib_rx_structures_free(if_ctx_t ctx)
 {
 	iflib_rxq_t rxq = ctx->ifc_rxqs;
-	int i;
+	if_shared_ctx_t sctx = ctx->ifc_sctx;
+	int i, j;
 
 	for (i = 0; i < ctx->ifc_softc_ctx.isc_nrxqsets; i++, rxq++) {
+		for (j = 0; j < sctx->isc_nrxqs; j++)
+			iflib_dma_free(&rxq->ifr_ifdi[j]);
 		iflib_rx_sds_free(rxq);
 #if defined(INET6) || defined(INET)
 		if (if_getcapabilities(ctx->ifc_ifp) & IFCAP_LRO)


More information about the svn-src-head mailing list