Date: Mon, 28 Jan 2013 00:15:45 +0000 (UTC) From: Marcel Moolenaar <marcel@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r246017 - in projects/altix2/sys: ia64/sgisn kern Message-ID: <201301280015.r0S0Fjq1043634@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: marcel Date: Mon Jan 28 00:15:44 2013 New Revision: 246017 URL: http://svnweb.freebsd.org/changeset/base/246017 Log: o Call BUSDMA_IOMMU_UNMAP for each segment, just like BUSDMA_IOMMU_MAP. o Implememt BUSDMA_UOMMU_UNMAP in sgisn_pcib. o Keep a bitmap of IOMMU entry (ATEs) for allocation purposes. Modified: projects/altix2/sys/ia64/sgisn/sgisn_pcib.c projects/altix2/sys/kern/busdma_if.m projects/altix2/sys/kern/subr_busdma.c Modified: projects/altix2/sys/ia64/sgisn/sgisn_pcib.c ============================================================================== --- projects/altix2/sys/ia64/sgisn/sgisn_pcib.c Sun Jan 27 23:33:42 2013 (r246016) +++ projects/altix2/sys/ia64/sgisn/sgisn_pcib.c Mon Jan 28 00:15:44 2013 (r246017) @@ -30,8 +30,10 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> +#include <sys/lock.h> #include <sys/module.h> #include <sys/malloc.h> +#include <sys/mutex.h> #include <sys/bus.h> #include <sys/busdma.h> #include <sys/pcpu.h> @@ -75,6 +77,8 @@ struct sgisn_pcib_softc { struct rman sc_iomem; uint32_t *sc_flush_intr[PCI_SLOTMAX + 1]; uint64_t *sc_flush_addr[PCI_SLOTMAX + 1]; + uint64_t sc_ate[PIC_REG_ATE_SIZE / 64]; + struct mtx sc_ate_mtx; }; static int sgisn_pcib_attach(device_t); @@ -109,6 +113,7 @@ static void sgisn_pcib_cfgwrite(device_t static int sgisn_pcib_iommu_xlate(device_t, device_t, busdma_mtag_t); static int sgisn_pcib_iommu_map(device_t, device_t, busdma_md_t, u_int, bus_addr_t *); +static int sgisn_pcib_iommu_unmap(device_t, device_t, busdma_md_t, u_int); static int sgisn_pcib_iommu_sync(device_t, device_t, busdma_md_t, u_int, bus_addr_t, bus_size_t); @@ -144,6 +149,7 @@ static device_method_t sgisn_pcib_method /* busdma interface */ DEVMETHOD(busdma_iommu_xlate, sgisn_pcib_iommu_xlate), DEVMETHOD(busdma_iommu_map, sgisn_pcib_iommu_map), + DEVMETHOD(busdma_iommu_unmap, sgisn_pcib_iommu_unmap), DEVMETHOD(busdma_iommu_sync, sgisn_pcib_iommu_sync), { 0, 0 } @@ -475,6 +481,8 @@ sgisn_pcib_attach(device_t dev) #endif bus_space_write_8(sc->sc_tag, sc->sc_hndl, PIC_REG_WGT_CTRL, ctrl); + mtx_init(&sc->sc_ate_mtx, device_get_nameunit(dev), NULL, MTX_SPIN); + fwflushsz = (PCI_SLOTMAX + 1) * sizeof(struct sgisn_fwflush); fwflush = contigmalloc(fwflushsz, M_TEMP, M_ZERO, 0UL, ~0UL, 16, 0); BUS_READ_IVAR(parent, dev, SHUB_IVAR_NASID, &ivar); @@ -574,8 +582,9 @@ sgisn_pcib_iommu_map(device_t bus, devic struct sgisn_pcib_softc *sc = device_get_softc(bus); busdma_tag_t tag; bus_addr_t maxaddr = 0x80000000UL; - bus_addr_t ba; - u_int flags; + bus_addr_t ba, size; + uint64_t bits; + u_int ate, bitshft, count, entry, flags; ba = *ba_p; @@ -595,39 +604,133 @@ sgisn_pcib_iommu_map(device_t bus, devic /* * 32-bit mapped DMA. - * - * XXX HACK START XXX */ - { - bus_addr_t size; - size_t count; - u_int entry; - - size = busdma_md_get_size(md, idx); - count = ((ba & SGISN_PCIB_PAGE_MASK) + size + - SGISN_PCIB_PAGE_MASK) >> SGISN_PCIB_PAGE_SHIFT; - - entry = 0; - - *ba_p = (1UL << 30) | (ba & SGISN_PCIB_PAGE_MASK) | - (SGISN_PCIB_PAGE_SIZE * entry); - - ba &= ~SGISN_PCIB_PAGE_MASK; - ba |= 1 << 0; /* valid */ - ba |= 1 << ((flags & BUSDMA_ALLOC_CONSISTENT) ? 4 : 3); - ba |= (u_long)sc->sc_fwbus->fw_hub_xid << 8; - - while (count > 0) { - bus_space_write_8(sc->sc_tag, sc->sc_hndl, - PIC_REG_ATE(entry), ba); - ba += SGISN_PCIB_PAGE_SIZE; - entry++; - count--; + size = busdma_md_get_size(md, idx); + count = ((ba & SGISN_PCIB_PAGE_MASK) + size + + SGISN_PCIB_PAGE_MASK) >> SGISN_PCIB_PAGE_SHIFT; + + /* Our bitmap allocation routine doesn't handle straddling longs. */ + if (count > 64) { + device_printf(sc->sc_dev, "IOMMU: more than 64 entries needed " + "for DMA\n"); + return (E2BIG); + } + + mtx_lock_spin(&sc->sc_ate_mtx); + + ate = 0; + entry = ~0; + while (ate < (PIC_REG_ATE_SIZE / 64) && entry == ~0) { + bits = sc->sc_ate[ate]; + /* Move to the next long if this one is full. */ + if (bits == ~0UL) { + ate++; + continue; } + /* If this long is empty, take it (catches count == 64). */ + if (bits == 0UL) { + bitshft = 0; + entry = ate * 64; + break; + } + /* Avoid undefined behaviour below for 1 << count. */ + if (count == 64) { + ate++; + continue; + } + bitshft = 0; + do { + if ((bits & ((1UL << count) - 1UL)) == 0) { + entry = ate * 64 + bitshft; + break; + } + while ((bits & 1UL) == 0) { + bits >>= 1; + bitshft++; + } + while (bitshft <= (64 - count) && (bits & 1UL) != 0) { + bits >>= 1; + bitshft++; + } + } while (bitshft <= (64 - count)); + if (entry == ~0) + ate++; + } + if (entry != ~0) { + KASSERT(ate < (PIC_REG_ATE_SIZE / 64), ("foo: ate")); + KASSERT(bitshft <= (64 - count), ("foo: bitshft")); + KASSERT(entry == (ate * 64 + bitshft), ("foo: math")); + bits = (count < 64) ? ((1UL << count) - 1UL) << bitshft : ~0UL; + KASSERT((sc->sc_ate[ate] & bits) == 0UL, ("foo: bits")); + sc->sc_ate[ate] |= bits; } + + mtx_unlock_spin(&sc->sc_ate_mtx); + + if (entry == ~0) { + device_printf(sc->sc_dev, "IOMMU: cannot find %u free entries " + "for DMA\n", count); + return (ENOSPC); + } + + *ba_p = (1UL << 30) | (ba & SGISN_PCIB_PAGE_MASK) | + (SGISN_PCIB_PAGE_SIZE * entry); + + ba &= ~SGISN_PCIB_PAGE_MASK; + ba |= 1 << 0; /* valid */ + ba |= 1 << ((flags & BUSDMA_ALLOC_CONSISTENT) ? 4 : 3); + ba |= (u_long)sc->sc_fwbus->fw_hub_xid << 8; + while (count > 0) { + bus_space_write_8(sc->sc_tag, sc->sc_hndl, + PIC_REG_ATE(entry), ba); + ba += SGISN_PCIB_PAGE_SIZE; + entry++; + count--; + } + return (0); +} + +static int +sgisn_pcib_iommu_unmap(device_t bus, device_t dev, busdma_md_t md, u_int idx) +{ + struct sgisn_pcib_softc *sc = device_get_softc(bus); + bus_addr_t ba, size; + uint64_t bits; + u_int ate, bitshft, count, entry; + + ba = busdma_md_get_busaddr(md, idx); + if ((ba >> 30) != 1) + return (0); + /* - * XXX HACK END XXX + * 32-bit mapped DMA */ + size = busdma_md_get_size(md, idx); + count = ((ba & SGISN_PCIB_PAGE_MASK) + size + + SGISN_PCIB_PAGE_MASK) >> SGISN_PCIB_PAGE_SHIFT; + ba &= (1 << 29) - 1; + entry = (ba >> SGISN_PCIB_PAGE_SHIFT); + + KASSERT(count <= 64, ("foo: count")); + KASSERT((entry + count) <= PIC_REG_ATE_SIZE, ("foo")); + bitshft = entry & 64; + KASSERT(bitshft <= (64 - count), ("foo: bitshft")); + bits = (count < 64) ? ((1UL << count) - 1UL) << bitshft : ~0UL; + ate = entry / 64; + + while (count > 0) { + bus_space_write_8(sc->sc_tag, sc->sc_hndl, + PIC_REG_ATE(entry), 0); + entry++; + count--; + } + + mtx_lock_spin(&sc->sc_ate_mtx); + + sc->sc_ate[ate] &= ~bits; + + mtx_unlock_spin(&sc->sc_ate_mtx); + return (0); } Modified: projects/altix2/sys/kern/busdma_if.m ============================================================================== --- projects/altix2/sys/kern/busdma_if.m Sun Jan 27 23:33:42 2013 (r246016) +++ projects/altix2/sys/kern/busdma_if.m Mon Jan 28 00:15:44 2013 (r246017) @@ -47,7 +47,8 @@ CODE { } static int - default_iommu_unmap(device_t bus, device_t dev, busdma_md_t md) + default_iommu_unmap(device_t bus, device_t dev, busdma_md_t md, + u_int idx) { return (0); } @@ -78,6 +79,7 @@ METHOD int iommu_unmap { device_t bus; device_t dev; busdma_md_t md; + u_int idx; } DEFAULT default_iommu_unmap; METHOD int iommu_sync { Modified: projects/altix2/sys/kern/subr_busdma.c ============================================================================== --- projects/altix2/sys/kern/subr_busdma.c Sun Jan 27 23:33:42 2013 (r246016) +++ projects/altix2/sys/kern/subr_busdma.c Mon Jan 28 00:15:44 2013 (r246017) @@ -430,11 +430,17 @@ _busdma_iommu_map(device_t dev, struct b static int _busdma_iommu_unmap(device_t dev, struct busdma_md *md) { + struct busdma_md_seg *seg; device_t bus; int error; bus = device_get_parent(dev); - error = BUSDMA_IOMMU_UNMAP(bus, dev, md); + error = 0; + TAILQ_FOREACH(seg, &md->md_seg, mds_chain) { + error = BUSDMA_IOMMU_UNMAP(bus, dev, md, seg->mds_idx); + if (error) + break; + } if (error) printf("%s: error=%d\n", __func__, error);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201301280015.r0S0Fjq1043634>