From owner-svn-src-projects@FreeBSD.ORG Sat Dec 29 22:26:02 2012 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 277FC7FF; Sat, 29 Dec 2012 22:26:02 +0000 (UTC) (envelope-from jeff@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id 0B88B8FC08; Sat, 29 Dec 2012 22:26:02 +0000 (UTC) Received: from svn.freebsd.org (svn.FreeBSD.org [8.8.178.70]) by svn.freebsd.org (8.14.5/8.14.5) with ESMTP id qBTMQ1qb061934; Sat, 29 Dec 2012 22:26:01 GMT (envelope-from jeff@svn.freebsd.org) Received: (from jeff@localhost) by svn.freebsd.org (8.14.5/8.14.5/Submit) id qBTMQ1HV061933; Sat, 29 Dec 2012 22:26:01 GMT (envelope-from jeff@svn.freebsd.org) Message-Id: <201212292226.qBTMQ1HV061933@svn.freebsd.org> From: Jeff Roberson Date: Sat, 29 Dec 2012 22:26:01 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r244839 - projects/physbio/sys/sparc64/sparc64 X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 29 Dec 2012 22:26:02 -0000 Author: jeff Date: Sat Dec 29 22:26:01 2012 New Revision: 244839 URL: http://svnweb.freebsd.org/changeset/base/244839 Log: - Make an attempt at loading physical addresses on iommu enabled sparcs. This is mostly a copy and paste of the virtual load function but I don't fully understand this code. Sponsored by: EMC / Isilon Storage Division Modified: projects/physbio/sys/sparc64/sparc64/iommu.c Modified: projects/physbio/sys/sparc64/sparc64/iommu.c ============================================================================== --- projects/physbio/sys/sparc64/sparc64/iommu.c Sat Dec 29 22:18:02 2012 (r244838) +++ projects/physbio/sys/sparc64/sparc64/iommu.c Sat Dec 29 22:26:01 2012 (r244839) @@ -854,11 +854,112 @@ static int iommu_dvmamap_load_phys(bus_dma_tag_t dmat, bus_dmamap_t map, vm_paddr_t buf, bus_size_t buflen, int flags, bus_dma_segment_t *segs, int *segp) { + bus_addr_t amask, dvmaddr, dvmoffs; + bus_size_t sgsize, esize; + struct iommu_state *is; + vm_offset_t voffs; + vm_paddr_t curaddr; + int error, firstpg, sgcnt; + u_int slot; + + is = dt->dt_cookie; + if (*segp == -1) { + if ((map->dm_flags & DMF_LOADED) != 0) { +#ifdef DIAGNOSTIC + printf("%s: map still in use\n", __func__); +#endif + bus_dmamap_unload(dt, map); + } + + /* + * Make sure that the map is not on a queue so that the + * resource list may be safely accessed and modified without + * needing the lock to cover the whole operation. + */ + IS_LOCK(is); + iommu_map_remq(is, map); + IS_UNLOCK(is); + + amask = dt->dt_alignment - 1; + } else + amask = 0; + KASSERT(buflen != 0, ("%s: buflen == 0!", __func__)); + if (buflen > dt->dt_maxsize) + return (EINVAL); + + if (segs == NULL) + segs = dt->dt_segments; + + voffs = buf & IO_PAGE_MASK; + + /* Try to find a slab that is large enough. */ + error = iommu_dvma_vallocseg(dt, is, map, voffs, buflen, amask, + &dvmaddr); + if (error != 0) + return (error); + + sgcnt = *segp; + firstpg = 1; + map->dm_flags &= ~DMF_STREAMED; + map->dm_flags |= iommu_use_streaming(is, map, buflen) != 0 ? + DMF_STREAMED : 0; + for (; buflen > 0; ) { + curaddr = buf; + + /* + * Compute the segment size, and adjust counts. + */ + sgsize = IO_PAGE_SIZE - ((u_long)buf & IO_PAGE_MASK); + if (buflen < sgsize) + sgsize = buflen; + + buflen -= sgsize; + buf += sgsize; + + dvmoffs = trunc_io_page(dvmaddr); + iommu_enter(is, dvmoffs, trunc_io_page(curaddr), + (map->dm_flags & DMF_STREAMED) != 0, flags); + if ((is->is_flags & IOMMU_FLUSH_CACHE) != 0) { + slot = IOTSBSLOT(dvmoffs); + if (buflen <= 0 || slot % 8 == 7) + IOMMU_WRITE8(is, is_iommu, IMR_CACHE_FLUSH, + is->is_ptsb + slot * 8); + } + + /* + * Chop the chunk up into segments of at most maxsegsz, but try + * to fill each segment as well as possible. + */ + if (!firstpg) { + esize = ulmin(sgsize, + dt->dt_maxsegsz - segs[sgcnt].ds_len); + segs[sgcnt].ds_len += esize; + sgsize -= esize; + dvmaddr += esize; + } + while (sgsize > 0) { + sgcnt++; + if (sgcnt >= dt->dt_nsegments) + return (EFBIG); + /* + * No extra alignment here - the common practice in + * the busdma code seems to be that only the first + * segment needs to satisfy the alignment constraints + * (and that only for bus_dmamem_alloc()ed maps). + * It is assumed that such tags have maxsegsize >= + * maxsize. + */ + esize = ulmin(sgsize, dt->dt_maxsegsz); + segs[sgcnt].ds_addr = dvmaddr; + segs[sgcnt].ds_len = esize; + sgsize -= esize; + dvmaddr += esize; + } - /* - * Did we fit? - */ - return (buflen != 0 ? EFBIG : 0); + firstpg = 0; + } + *segp = sgcnt; + return (0); } /*