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>