Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 27 Feb 2018 01:48:13 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r330049 - in head/sys/dev: mpr mps
Message-ID:  <201802270148.w1R1mDu3025055@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Tue Feb 27 01:48:13 2018
New Revision: 330049
URL: https://svnweb.freebsd.org/changeset/base/330049

Log:
  Allow physically non-contiguous chain frames allocation in mps(4)/mpr(4).
  
  Chain frames required to satisfy all 2K of declared I/Os of 128KB each take
  more then a megabyte of a physical memory, all of which existing code tries
  allocate as physically contiguous.  This patch removes that physical
  contiguousness requirement, leaving only virtual contiguousness.  I was
  thinking about other ways of allocation, but the less granular allocation
  becomes, the bigger is the overhead and/or complexity, reaching about 100%
  overhead if allocate each frame separately.
  
  The patch also bumps the chain frames hard limit from 2K to 16K.  It is more
  than enough for the case of default REQ_FRAMES and MAXPHYS (the drivers will
  allocate less than that automatically), while in case of increased MAXPHYS
  it will control maximal memory usage.
  
  Sponsored by:	iXsystems, Inc.
  Differential Revision:	https://reviews.freebsd.org/D14420

Modified:
  head/sys/dev/mpr/mpr.c
  head/sys/dev/mpr/mprvar.h
  head/sys/dev/mps/mps.c
  head/sys/dev/mps/mpsvar.h

Modified: head/sys/dev/mpr/mpr.c
==============================================================================
--- head/sys/dev/mpr/mpr.c	Tue Feb 27 01:36:43 2018	(r330048)
+++ head/sys/dev/mpr/mpr.c	Tue Feb 27 01:48:13 2018	(r330049)
@@ -382,7 +382,7 @@ mpr_transition_operational(struct mpr_softc *sc)
 static void
 mpr_resize_queues(struct mpr_softc *sc)
 {
-	u_int reqcr, prireqcr, maxio, sges_per_frame;
+	u_int reqcr, prireqcr, maxio, sges_per_frame, chain_seg_size;
 
 	/*
 	 * Size the queues. Since the reply queues always need one free
@@ -413,15 +413,11 @@ mpr_resize_queues(struct mpr_softc *sc)
 	 * the size of an IEEE Simple SGE.
 	 */
 	if (sc->facts->MsgVersion >= MPI2_VERSION_02_05) {
-		sc->chain_seg_size =
-		    htole16(sc->facts->IOCMaxChainSegmentSize);
-		if (sc->chain_seg_size == 0) {
-			sc->chain_frame_size = MPR_DEFAULT_CHAIN_SEG_SIZE *
-			    MPR_MAX_CHAIN_ELEMENT_SIZE;
-		} else {
-			sc->chain_frame_size = sc->chain_seg_size *
-			    MPR_MAX_CHAIN_ELEMENT_SIZE;
-		}
+		chain_seg_size = htole16(sc->facts->IOCMaxChainSegmentSize);
+		if (chain_seg_size == 0)
+			chain_seg_size = MPR_DEFAULT_CHAIN_SEG_SIZE;
+		sc->chain_frame_size = chain_seg_size *
+		    MPR_MAX_CHAIN_ELEMENT_SIZE;
 	} else {
 		sc->chain_frame_size = sc->reqframesz;
 	}
@@ -766,11 +762,11 @@ mpr_iocfacts_free(struct mpr_softc *sc)
 	if (sc->queues_dmat != NULL)
 		bus_dma_tag_destroy(sc->queues_dmat);
 
-	if (sc->chain_busaddr != 0)
+	if (sc->chain_frames != NULL) {
 		bus_dmamap_unload(sc->chain_dmat, sc->chain_map);
-	if (sc->chain_frames != NULL)
 		bus_dmamem_free(sc->chain_dmat, sc->chain_frames,
 		    sc->chain_map);
+	}
 	if (sc->chain_dmat != NULL)
 		bus_dma_tag_destroy(sc->chain_dmat);
 
@@ -1411,11 +1407,36 @@ mpr_alloc_replies(struct mpr_softc *sc)
 	return (0);
 }
 
+static void
+mpr_load_chains_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
+{
+	struct mpr_softc *sc = arg;
+	struct mpr_chain *chain;
+	bus_size_t bo;
+	int i, o, s;
+
+	if (error != 0)
+		return;
+
+	for (i = 0, o = 0, s = 0; s < nsegs; s++) {
+		for (bo = 0; bo + sc->chain_frame_size <= segs[s].ds_len;
+		    bo += sc->chain_frame_size) {
+			chain = &sc->chains[i++];
+			chain->chain =(MPI2_SGE_IO_UNION *)(sc->chain_frames+o);
+			chain->chain_busaddr = segs[s].ds_addr + bo;
+			o += sc->chain_frame_size;
+			mpr_free_chain(sc, chain);
+		}
+		if (bo != segs[s].ds_len)
+			o += segs[s].ds_len - bo;
+	}
+	sc->chain_free_lowwater = i;
+}
+
 static int
 mpr_alloc_requests(struct mpr_softc *sc)
 {
 	struct mpr_command *cm;
-	struct mpr_chain *chain;
 	int i, rsize, nsegs;
 
 	rsize = sc->reqframesz * sc->num_reqs;
@@ -1444,31 +1465,39 @@ mpr_alloc_requests(struct mpr_softc *sc)
 	mpr_dprint(sc, MPR_INIT, "request frames busaddr= %#016jx size= %d\n",
 	    (uintmax_t)sc->req_busaddr, rsize);
 
+	sc->chains = malloc(sizeof(struct mpr_chain) * sc->num_chains, M_MPR,
+	    M_NOWAIT | M_ZERO);
+	if (!sc->chains) {
+		mpr_dprint(sc, MPR_ERROR, "Cannot allocate chain memory\n");
+		return (ENOMEM);
+	}
 	rsize = sc->chain_frame_size * sc->num_chains;
-        if (bus_dma_tag_create( sc->mpr_parent_dmat,    /* parent */
+	if (bus_dma_tag_create( sc->mpr_parent_dmat,	/* parent */
 				16, 0,			/* algnmnt, boundary */
 				BUS_SPACE_MAXADDR,	/* lowaddr */
 				BUS_SPACE_MAXADDR,	/* highaddr */
 				NULL, NULL,		/* filter, filterarg */
-                                rsize,			/* maxsize */
-                                1,			/* nsegments */
-                                rsize,			/* maxsegsize */
-                                0,			/* flags */
-                                NULL, NULL,		/* lockfunc, lockarg */
-                                &sc->chain_dmat)) {
+				rsize,			/* maxsize */
+				howmany(rsize, PAGE_SIZE), /* nsegments */
+				rsize,			/* maxsegsize */
+				0,			/* flags */
+				NULL, NULL,		/* lockfunc, lockarg */
+				&sc->chain_dmat)) {
 		mpr_dprint(sc, MPR_ERROR, "Cannot allocate chain DMA tag\n");
 		return (ENOMEM);
-        }
-        if (bus_dmamem_alloc(sc->chain_dmat, (void **)&sc->chain_frames,
-	    BUS_DMA_NOWAIT, &sc->chain_map)) {
+	}
+	if (bus_dmamem_alloc(sc->chain_dmat, (void **)&sc->chain_frames,
+	    BUS_DMA_NOWAIT | BUS_DMA_ZERO, &sc->chain_map)) {
 		mpr_dprint(sc, MPR_ERROR, "Cannot allocate chain memory\n");
 		return (ENOMEM);
-        }
-        bzero(sc->chain_frames, rsize);
-        bus_dmamap_load(sc->chain_dmat, sc->chain_map, sc->chain_frames, rsize,
-	    mpr_memaddr_cb, &sc->chain_busaddr, 0);
-	mpr_dprint(sc, MPR_INIT, "chain frames busaddr= %#016jx size= %d\n",
-	    (uintmax_t)sc->chain_busaddr, rsize);
+	}
+	if (bus_dmamap_load(sc->chain_dmat, sc->chain_map, sc->chain_frames,
+	    rsize, mpr_load_chains_cb, sc, BUS_DMA_NOWAIT)) {
+		mpr_dprint(sc, MPR_ERROR, "Cannot load chain memory\n");
+		bus_dmamem_free(sc->chain_dmat, sc->chain_frames,
+		    sc->chain_map);
+		return (ENOMEM);
+	}
 
 	rsize = MPR_SENSE_LEN * sc->num_reqs;
 	if (bus_dma_tag_create( sc->mpr_parent_dmat,    /* parent */
@@ -1495,22 +1524,6 @@ mpr_alloc_requests(struct mpr_softc *sc)
 	    mpr_memaddr_cb, &sc->sense_busaddr, 0);
 	mpr_dprint(sc, MPR_INIT, "sense frames busaddr= %#016jx size= %d\n",
 	    (uintmax_t)sc->sense_busaddr, rsize);
-
-	sc->chains = malloc(sizeof(struct mpr_chain) * sc->num_chains, M_MPR,
-	    M_WAITOK | M_ZERO);
-	if (!sc->chains) {
-		mpr_dprint(sc, MPR_ERROR, "Cannot allocate chain memory\n");
-		return (ENOMEM);
-	}
-	for (i = 0; i < sc->num_chains; i++) {
-		chain = &sc->chains[i];
-		chain->chain = (MPI2_SGE_IO_UNION *)(sc->chain_frames +
-		    i * sc->chain_frame_size);
-		chain->chain_busaddr = sc->chain_busaddr +
-		    i * sc->chain_frame_size;
-		mpr_free_chain(sc, chain);
-		sc->chain_free_lowwater++;
-	}
 
 	/*
 	 * Allocate NVMe PRP Pages for NVMe SGL support only if the FW supports

Modified: head/sys/dev/mpr/mprvar.h
==============================================================================
--- head/sys/dev/mpr/mprvar.h	Tue Feb 27 01:36:43 2018	(r330048)
+++ head/sys/dev/mpr/mprvar.h	Tue Feb 27 01:48:13 2018	(r330049)
@@ -41,7 +41,7 @@
 #define MPR_PRI_REQ_FRAMES	128
 #define MPR_EVT_REPLY_FRAMES	32
 #define MPR_REPLY_FRAMES	MPR_REQ_FRAMES
-#define MPR_CHAIN_FRAMES	2048
+#define MPR_CHAIN_FRAMES	16384
 #define MPR_MAXIO_PAGES		(-1)
 #define MPR_SENSE_LEN		SSD_FULL_SIZE
 #define MPR_MSI_MAX		1
@@ -322,7 +322,6 @@ struct mpr_softc {
 	u_int				maxio;
 	int				chain_free_lowwater;
 	uint32_t			chain_frame_size;
-	uint16_t			chain_seg_size;
 	int				prp_buffer_size;
 	int				prp_pages_free;
 	int				prp_pages_free_lowwater;
@@ -389,7 +388,6 @@ struct mpr_softc {
 	bus_dmamap_t			sense_map;
 
 	uint8_t				*chain_frames;
-	bus_addr_t			chain_busaddr;
 	bus_dma_tag_t			chain_dmat;
 	bus_dmamap_t			chain_map;
 

Modified: head/sys/dev/mps/mps.c
==============================================================================
--- head/sys/dev/mps/mps.c	Tue Feb 27 01:36:43 2018	(r330048)
+++ head/sys/dev/mps/mps.c	Tue Feb 27 01:48:13 2018	(r330049)
@@ -743,11 +743,11 @@ mps_iocfacts_free(struct mps_softc *sc)
 	if (sc->queues_dmat != NULL)
 		bus_dma_tag_destroy(sc->queues_dmat);
 
-	if (sc->chain_busaddr != 0)
+	if (sc->chain_frames != NULL) {
 		bus_dmamap_unload(sc->chain_dmat, sc->chain_map);
-	if (sc->chain_frames != NULL)
 		bus_dmamem_free(sc->chain_dmat, sc->chain_frames,
 		    sc->chain_map);
+	}
 	if (sc->chain_dmat != NULL)
 		bus_dma_tag_destroy(sc->chain_dmat);
 
@@ -1370,11 +1370,36 @@ mps_alloc_replies(struct mps_softc *sc)
 	return (0);
 }
 
+static void
+mps_load_chains_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
+{
+	struct mps_softc *sc = arg;
+	struct mps_chain *chain;
+	bus_size_t bo;
+	int i, o, s;
+
+	if (error != 0)
+		return;
+
+	for (i = 0, o = 0, s = 0; s < nsegs; s++) {
+		for (bo = 0; bo + sc->reqframesz <= segs[s].ds_len;
+		    bo += sc->reqframesz) {
+			chain = &sc->chains[i++];
+			chain->chain =(MPI2_SGE_IO_UNION *)(sc->chain_frames+o);
+			chain->chain_busaddr = segs[s].ds_addr + bo;
+			o += sc->reqframesz;
+			mps_free_chain(sc, chain);
+		}
+		if (bo != segs[s].ds_len)
+			o += segs[s].ds_len - bo;
+	}
+	sc->chain_free_lowwater = i;
+}
+
 static int
 mps_alloc_requests(struct mps_softc *sc)
 {
 	struct mps_command *cm;
-	struct mps_chain *chain;
 	int i, rsize, nsegs;
 
 	rsize = sc->reqframesz * sc->num_reqs;
@@ -1403,31 +1428,39 @@ mps_alloc_requests(struct mps_softc *sc)
 	mps_dprint(sc, MPS_INIT, "request frames busaddr= %#016jx size= %d\n",
 	    (uintmax_t)sc->req_busaddr, rsize);
 
+	sc->chains = malloc(sizeof(struct mps_chain) * sc->num_chains, M_MPT2,
+	    M_NOWAIT | M_ZERO);
+	if (!sc->chains) {
+		mps_dprint(sc, MPS_ERROR, "Cannot allocate chain memory\n");
+		return (ENOMEM);
+	}
 	rsize = sc->reqframesz * sc->num_chains;
-        if (bus_dma_tag_create( sc->mps_parent_dmat,    /* parent */
+	if (bus_dma_tag_create( sc->mps_parent_dmat,	/* parent */
 				16, 0,			/* algnmnt, boundary */
 				BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
 				BUS_SPACE_MAXADDR,	/* highaddr */
 				NULL, NULL,		/* filter, filterarg */
-                                rsize,			/* maxsize */
-                                1,			/* nsegments */
-                                rsize,			/* maxsegsize */
-                                0,			/* flags */
-                                NULL, NULL,		/* lockfunc, lockarg */
-                                &sc->chain_dmat)) {
+				rsize,			/* maxsize */
+				howmany(rsize, PAGE_SIZE), /* nsegments */
+				rsize,			/* maxsegsize */
+				0,			/* flags */
+				NULL, NULL,		/* lockfunc, lockarg */
+				&sc->chain_dmat)) {
 		mps_dprint(sc, MPS_ERROR, "Cannot allocate chain DMA tag\n");
 		return (ENOMEM);
-        }
-        if (bus_dmamem_alloc(sc->chain_dmat, (void **)&sc->chain_frames,
-	    BUS_DMA_NOWAIT, &sc->chain_map)) {
+	}
+	if (bus_dmamem_alloc(sc->chain_dmat, (void **)&sc->chain_frames,
+	    BUS_DMA_NOWAIT | BUS_DMA_ZERO, &sc->chain_map)) {
 		mps_dprint(sc, MPS_ERROR, "Cannot allocate chain memory\n");
 		return (ENOMEM);
-        }
-        bzero(sc->chain_frames, rsize);
-        bus_dmamap_load(sc->chain_dmat, sc->chain_map, sc->chain_frames, rsize,
-	    mps_memaddr_cb, &sc->chain_busaddr, 0);
-	mps_dprint(sc, MPS_INIT, "chain frames busaddr= %#016jx size= %d\n",
-	    (uintmax_t)sc->chain_busaddr, rsize);
+	}
+	if (bus_dmamap_load(sc->chain_dmat, sc->chain_map, sc->chain_frames,
+	    rsize, mps_load_chains_cb, sc, BUS_DMA_NOWAIT)) {
+		mps_dprint(sc, MPS_ERROR, "Cannot load chain memory\n");
+		bus_dmamem_free(sc->chain_dmat, sc->chain_frames,
+		    sc->chain_map);
+		return (ENOMEM);
+	}
 
 	rsize = MPS_SENSE_LEN * sc->num_reqs;
         if (bus_dma_tag_create( sc->mps_parent_dmat,    /* parent */
@@ -1454,22 +1487,6 @@ mps_alloc_requests(struct mps_softc *sc)
 	    mps_memaddr_cb, &sc->sense_busaddr, 0);
 	mps_dprint(sc, MPS_INIT, "sense frames busaddr= %#016jx size= %d\n",
 	    (uintmax_t)sc->sense_busaddr, rsize);
-
-	sc->chains = malloc(sizeof(struct mps_chain) * sc->num_chains, M_MPT2,
-	    M_WAITOK | M_ZERO);
-	if(!sc->chains) {
-		mps_dprint(sc, MPS_ERROR, "Cannot allocate chains memory\n");
-		return (ENOMEM);
-	}
-	for (i = 0; i < sc->num_chains; i++) {
-		chain = &sc->chains[i];
-		chain->chain = (MPI2_SGE_IO_UNION *)(sc->chain_frames +
-		    i * sc->reqframesz);
-		chain->chain_busaddr = sc->chain_busaddr +
-		    i * sc->reqframesz;
-		mps_free_chain(sc, chain);
-		sc->chain_free_lowwater++;
-	}
 
 	nsegs = (sc->maxio / PAGE_SIZE) + 1;
         if (bus_dma_tag_create( sc->mps_parent_dmat,    /* parent */

Modified: head/sys/dev/mps/mpsvar.h
==============================================================================
--- head/sys/dev/mps/mpsvar.h	Tue Feb 27 01:36:43 2018	(r330048)
+++ head/sys/dev/mps/mpsvar.h	Tue Feb 27 01:48:13 2018	(r330049)
@@ -43,7 +43,7 @@
 #define MPS_PRI_REQ_FRAMES	128
 #define MPS_EVT_REPLY_FRAMES	32
 #define MPS_REPLY_FRAMES	MPS_REQ_FRAMES
-#define MPS_CHAIN_FRAMES	2048
+#define MPS_CHAIN_FRAMES	16384
 #define MPS_MAXIO_PAGES		(-1)
 #define MPS_SENSE_LEN		SSD_FULL_SIZE
 #define MPS_MSI_MAX		1
@@ -378,7 +378,6 @@ struct mps_softc {
 	bus_dmamap_t			sense_map;
 
 	uint8_t				*chain_frames;
-	bus_addr_t			chain_busaddr;
 	bus_dma_tag_t			chain_dmat;
 	bus_dmamap_t			chain_map;
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201802270148.w1R1mDu3025055>