Page MenuHomeFreeBSD

D42559.diff
No OneTemporary

D42559.diff

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
@@ -980,6 +980,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 */
@@ -1434,6 +1439,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 concern.
+ */
if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */
4, 0, /* algnmnt, boundary */
BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
@@ -1668,6 +1679,22 @@
sc->max_host_ios = sc->facts.max_reqs -
(MPI3MR_INTERNALCMDS_RESVD + 1);
+ /*
+ * Set 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.
+ */
+ 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;
}
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,6 +273,16 @@
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 could retroactively 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 */

File Metadata

Mime Type
text/plain
Expires
Sat, Nov 16, 9:52 PM (21 h, 30 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14664973
Default Alt Text
D42559.diff (2 KB)

Event Timeline