diff --git a/sys/dev/mpi3mr/mpi3mr.h b/sys/dev/mpi3mr/mpi3mr.h --- a/sys/dev/mpi3mr/mpi3mr.h +++ b/sys/dev/mpi3mr/mpi3mr.h @@ -544,7 +544,8 @@ char name[MPI3MR_NAME_LENGTH]; char driver_name[MPI3MR_NAME_LENGTH]; int bars; - int dma_mask; + bus_addr_t dma_loaddr; + bus_addr_t dma_hiaddr; u_int mpi3mr_debug; struct mpi3mr_reset reset; int max_msix_vectors; diff --git a/sys/dev/mpi3mr/mpi3mr.c b/sys/dev/mpi3mr/mpi3mr.c --- a/sys/dev/mpi3mr/mpi3mr.c +++ b/sys/dev/mpi3mr/mpi3mr.c @@ -604,8 +604,8 @@ if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 4, 0, /* algnmnt, boundary */ - BUS_SPACE_MAXADDR_32BIT,/* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ + sc->dma_loaddr, /* lowaddr */ + sc->dma_hiaddr, /* highaddr */ NULL, NULL, /* filter, filterarg */ op_reply_q->qsz, /* maxsize */ 1, /* nsegments */ @@ -619,7 +619,7 @@ if (bus_dmamem_alloc(op_reply_q->q_base_tag, (void **)&op_reply_q->q_base, BUS_DMA_NOWAIT, &op_reply_q->q_base_dmamap)) { - mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate replies memory\n"); + mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Cannot allocate replies memory\n", __func__); return (ENOMEM); } bzero(op_reply_q->q_base, op_reply_q->qsz); @@ -750,8 +750,8 @@ if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 4, 0, /* algnmnt, boundary */ - BUS_SPACE_MAXADDR_32BIT,/* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ + sc->dma_loaddr, /* lowaddr */ + sc->dma_hiaddr, /* highaddr */ NULL, NULL, /* filter, filterarg */ op_req_q->qsz, /* maxsize */ 1, /* nsegments */ @@ -765,7 +765,7 @@ if (bus_dmamem_alloc(op_req_q->q_base_tag, (void **)&op_req_q->q_base, BUS_DMA_NOWAIT, &op_req_q->q_base_dmamap)) { - mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate replies memory\n"); + mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Cannot allocate replies memory\n", __func__); return (ENOMEM); } @@ -981,6 +981,11 @@ sc->admin_reply_ephase = 1; if (!sc->admin_req) { + /* + * We need to create the tag for the admin queue to get the + * iofacts to see how many bits the controller decodes. Solve + * this chicken and egg problem by only doing lower 4GB dma. + */ if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 4, 0, /* algnmnt, boundary */ BUS_SPACE_MAXADDR_32BIT,/* lowaddr */ @@ -998,7 +1003,7 @@ if (bus_dmamem_alloc(sc->admin_req_tag, (void **)&sc->admin_req, BUS_DMA_NOWAIT, &sc->admin_req_dmamap)) { - mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate replies memory\n"); + mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Cannot allocate replies memory\n", __func__); return (ENOMEM); } bzero(sc->admin_req, sc->admin_req_q_sz); @@ -1036,7 +1041,7 @@ if (bus_dmamem_alloc(sc->admin_reply_tag, (void **)&sc->admin_reply, BUS_DMA_NOWAIT, &sc->admin_reply_dmamap)) { - mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate replies memory\n"); + mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Cannot allocate replies memory\n", __func__); return (ENOMEM); } bzero(sc->admin_reply, sc->admin_reply_q_sz); @@ -1435,6 +1440,12 @@ MPI3_SGE_FLAGS_END_OF_LIST); + /* + * We can't use sc->dma_loaddr / hiaddr here. We set those only after we + * get the iocfacts. So allocate in the lower 4GB. The amount of data is + * tiny and we don't do this that often, so any bouncing we might have + * to do isn't a cause for concernt. + */ if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 4, 0, /* algnmnt, boundary */ BUS_SPACE_MAXADDR_32BIT,/* lowaddr */ @@ -1669,6 +1680,23 @@ sc->max_host_ios = sc->facts.max_reqs - (MPI3MR_INTERNALCMDS_RESVD + 1); + /* + * Setup the dma mask for the card. dma_mask is the number of bits that + * can have bits set in them. Translate this into bus_dma loaddr/hiaddr + * args. Add sanity for more bits than address space or other overflow + * situations. Assumes that BUS_SPACE_MAXADDR can fit into a bus_addr_t + * and is defined best for this platform. + */ + if (sc->facts.dma_mask == 0 || + (sc->facts.dma_mask >= sizeof(bus_addr_t) * 8)) + sc->dma_loaddr = BUS_SPACE_MAXADDR; + else + sc->dma_loaddr = ~((1ull << sc->facts.dma_mask) - 1); + sc->dma_hiaddr = BUS_SPACE_MAXADDR; + mpi3mr_dprint(sc, MPI3MR_INFO, + "dma_mask bits: %d loaddr 0x%jx hiaddr 0x%jx\n", + sc->facts.dma_mask, sc->dma_loaddr, sc->dma_hiaddr); + return retval; } @@ -1704,8 +1732,8 @@ if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 16, 0, /* algnmnt, boundary */ - BUS_SPACE_MAXADDR_32BIT,/* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ + sc->dma_loaddr, /* lowaddr */ + sc->dma_hiaddr, /* highaddr */ NULL, NULL, /* filter, filterarg */ sz, /* maxsize */ 1, /* nsegments */ @@ -1740,8 +1768,8 @@ if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 8, 0, /* algnmnt, boundary */ - BUS_SPACE_MAXADDR_32BIT,/* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ + sc->dma_loaddr, /* lowaddr */ + sc->dma_hiaddr, /* highaddr */ NULL, NULL, /* filter, filterarg */ sz, /* maxsize */ 1, /* nsegments */ @@ -1774,8 +1802,8 @@ if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 4, 0, /* algnmnt, boundary */ - BUS_SPACE_MAXADDR_32BIT,/* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ + sc->dma_loaddr, /* lowaddr */ + sc->dma_hiaddr, /* highaddr */ NULL, NULL, /* filter, filterarg */ sz, /* maxsize */ 1, /* nsegments */ @@ -1808,8 +1836,8 @@ if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 8, 0, /* algnmnt, boundary */ - BUS_SPACE_MAXADDR_32BIT,/* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ + sc->dma_loaddr, /* lowaddr */ + sc->dma_hiaddr, /* highaddr */ NULL, NULL, /* filter, filterarg */ sz, /* maxsize */ 1, /* nsegments */ @@ -1945,8 +1973,8 @@ if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 4, 0, /* algnmnt, boundary */ - BUS_SPACE_MAXADDR_32BIT,/* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ + sc->dma_loaddr, /* lowaddr */ + sc->dma_hiaddr, /* highaddr */ NULL, NULL, /* filter, filterarg */ fw_pkg_ver_len, /* maxsize */ 1, /* nsegments */ @@ -2066,8 +2094,8 @@ if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 4, 0, /* algnmnt, boundary */ - BUS_SPACE_MAXADDR_32BIT,/* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ + sc->dma_loaddr, /* lowaddr */ + sc->dma_hiaddr, /* highaddr */ NULL, NULL, /* filter, filterarg */ drvr_info_len, /* maxsize */ 1, /* nsegments */ @@ -2482,8 +2510,8 @@ if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 4096, 0, /* algnmnt, boundary */ - BUS_SPACE_MAXADDR_32BIT,/* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ + sc->dma_loaddr, /* lowaddr */ + sc->dma_hiaddr, /* highaddr */ NULL, NULL, /* filter, filterarg */ sz, /* maxsize */ 1, /* nsegments */ @@ -2558,8 +2586,8 @@ sc->pel_seq_number_sz = sizeof(Mpi3PELSeq_t); if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 4, 0, /* alignment, boundary */ - BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ + sc->dma_loaddr, /* lowaddr */ + sc->dma_hiaddr, /* highaddr */ NULL, NULL, /* filter, filterarg */ sc->pel_seq_number_sz, /* maxsize */ 1, /* nsegments */ @@ -4906,8 +4934,8 @@ nsegs = MPI3MR_SG_DEPTH; ret = bus_dma_tag_create( sc->mpi3mr_parent_dmat, /* parent */ 1, 0, /* algnmnt, boundary */ - BUS_SPACE_MAXADDR, /* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ + sc->dma_loaddr, /* lowaddr */ + sc->dma_hiaddr, /* highaddr */ NULL, NULL, /* filter, filterarg */ MAXPHYS,/* maxsize */ nsegs, /* nsegments */ @@ -5080,8 +5108,8 @@ if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 4, 0, /* algnmnt, boundary */ - BUS_SPACE_MAXADDR_32BIT,/* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ + sc->dma_loaddr, /* lowaddr */ + sc->dma_hiaddr, /* highaddr */ NULL, NULL, /* filter, filterarg */ mem_desc->size, /* maxsize */ 1, /* nsegments */ @@ -5095,7 +5123,7 @@ if (bus_dmamem_alloc(mem_desc->tag, (void **)&mem_desc->addr, BUS_DMA_NOWAIT, &mem_desc->dmamap)) { - mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate replies memory\n"); + mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Cannot allocate replies memory\n", __func__); goto out_failed; } bzero(mem_desc->addr, mem_desc->size); @@ -5110,8 +5138,8 @@ mem_desc->size = MPI3MR_4K_PGSZ; if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 4, 0, /* algnmnt, boundary */ - BUS_SPACE_MAXADDR_32BIT,/* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ + sc->dma_loaddr, /* lowaddr */ + sc->dma_hiaddr, /* highaddr */ NULL, NULL, /* filter, filterarg */ mem_desc->size, /* maxsize */ 1, /* nsegments */ @@ -5125,7 +5153,7 @@ if (bus_dmamem_alloc(mem_desc->tag, (void **)&mem_desc->addr, BUS_DMA_NOWAIT, &mem_desc->dmamap)) { - mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate replies memory\n"); + mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Cannot allocate replies memory\n", __func__); goto out_failed; } bzero(mem_desc->addr, mem_desc->size); @@ -5139,8 +5167,8 @@ mem_desc->size = MPI3MR_4K_PGSZ; if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 4, 0, /* algnmnt, boundary */ - BUS_SPACE_MAXADDR_32BIT,/* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ + sc->dma_loaddr, /* lowaddr */ + sc->dma_hiaddr, /* highaddr */ NULL, NULL, /* filter, filterarg */ mem_desc->size, /* maxsize */ 1, /* nsegments */ diff --git a/sys/dev/mpi3mr/mpi3mr_app.c b/sys/dev/mpi3mr/mpi3mr_app.c --- a/sys/dev/mpi3mr/mpi3mr_app.c +++ b/sys/dev/mpi3mr/mpi3mr_app.c @@ -336,8 +336,8 @@ sc->nvme_encap_prp_sz = 0; if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 4, 0, /* algnmnt, boundary */ - BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ + sc->dma_loaddr, /* lowaddr */ + sc->dma_hiaddr, /* highaddr */ NULL, NULL, /* filter, filterarg */ dev_pgsz, /* maxsize */ 1, /* nsegments */ diff --git a/sys/dev/mpi3mr/mpi3mr_pci.c b/sys/dev/mpi3mr/mpi3mr_pci.c --- a/sys/dev/mpi3mr/mpi3mr_pci.c +++ b/sys/dev/mpi3mr/mpi3mr_pci.c @@ -273,10 +273,20 @@ sc->mpi3mr_btag = rman_get_bustag(sc->mpi3mr_regs_resource); sc->mpi3mr_bhandle = rman_get_bushandle(sc->mpi3mr_regs_resource); + /* + * XXX perhaps we should move this to after we read iocfacts and use + * that to create the proper parent tag. However, to get the iocfacts we + * need to have a dmatag for both the admin queue and the iocfacts dma + * transfer. So for now, we just create a 'no restriction' tag and use + * sc->dma_loaddr for all the other tag_create calls to get the right + * value. It would be nice if one would retro-actively adjust a created + * tag. The Linux driver effectively does this by setting the dma_mask + * on the device. + */ /* Allocate the parent DMA tag */ if (bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */ 1, 0, /* algnmnt, boundary */ - BUS_SPACE_MAXADDR_32BIT,/* lowaddr */ + BUS_SPACE_MAXADDR, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ BUS_SPACE_MAXSIZE_32BIT,/* maxsize */