From owner-svn-src-projects@FreeBSD.ORG Sun Jul 1 17:06:22 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 23370106566C; Sun, 1 Jul 2012 17:06:22 +0000 (UTC) (envelope-from marcel@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 0E10B8FC12; Sun, 1 Jul 2012 17:06:22 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q61H6LR5013811; Sun, 1 Jul 2012 17:06:21 GMT (envelope-from marcel@svn.freebsd.org) Received: (from marcel@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q61H6L0x013809; Sun, 1 Jul 2012 17:06:21 GMT (envelope-from marcel@svn.freebsd.org) Message-Id: <201207011706.q61H6L0x013809@svn.freebsd.org> From: Marcel Moolenaar Date: Sun, 1 Jul 2012 17:06:21 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r237932 - projects/altix2/sys/kern X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 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: Sun, 01 Jul 2012 17:06:22 -0000 Author: marcel Date: Sun Jul 1 17:06:21 2012 New Revision: 237932 URL: http://svn.freebsd.org/changeset/base/237932 Log: Dump a milestone: we see disks on the SCSI bus with isp(4) using the new busdma/mi implementation: 1. Implement load_linear using a common support function. The support function takes a pmap_t, virtual address and length and extends the last segment or appends new segments to the memory descriptor. 2. Implement unload as well now that we're getting too functional not to have it implemented. 3. Comment-out dump routines and other debugging printfs. It's time now to use KTR or other means to have the ability present without it interfering with normal operation. 4. Add a first-line of pretection: check arguments and return EINVAL when we're displeased with what;s given to us. Note that for the load_* functions we need a good definition of which errors are being returned directly and which errors are being relayed via the callback. Modified: projects/altix2/sys/kern/subr_busdma.c Modified: projects/altix2/sys/kern/subr_busdma.c ============================================================================== --- projects/altix2/sys/kern/subr_busdma.c Sun Jul 1 16:26:07 2012 (r237931) +++ projects/altix2/sys/kern/subr_busdma.c Sun Jul 1 17:06:21 2012 (r237932) @@ -73,7 +73,7 @@ struct busdma_md { struct busdma_tag *md_tag; u_int md_flags; u_int md_nsegs; - TAILQ_HEAD(, busdma_md_seg) md_seg; + TAILQ_HEAD(busdma_md_head, busdma_md_seg) md_seg; }; #define BUSDMA_MD_FLAG_ALLOCATED 0x1 /* busdma_mem_alloc() created @@ -156,6 +156,7 @@ SYSINIT(busdma_kmem, SI_SUB_KMEM, SI_ORD /* Section 3.2: Debugging & tracing. */ +#if 0 static void _busdma_mtag_dump(const char *func, device_t dev, struct busdma_mtag *mtag) { @@ -167,7 +168,9 @@ _busdma_mtag_dump(const char *func, devi (uintmax_t)mtag->dmt_maxsz, (uintmax_t)mtag->dmt_align, (uintmax_t)mtag->dmt_bndry); } +#endif +#if 0 static void _busdma_tag_dump(const char *func, device_t dev, struct busdma_tag *tag) { @@ -180,7 +183,9 @@ _busdma_tag_dump(const char *func, devic (uintmax_t)tag->dt_maxsz, tag->dt_nsegs, (uintmax_t)tag->dt_maxsegsz); } +#endif +#if 0 static void _busdma_md_dump(const char *func, device_t dev, struct busdma_md *md) { @@ -205,6 +210,7 @@ _busdma_md_dump(const char *func, device } printf("]\n"); } +#endif /* Section 3.3: API support functions. */ @@ -213,10 +219,14 @@ _busdma_md_get_seg(struct busdma_md *md, { struct busdma_md_seg *seg; + if (md == NULL || idx >= md->md_nsegs) + return (NULL); + TAILQ_FOREACH(seg, &md->md_seg, mds_chain) { if (seg->mds_idx == idx) return (seg); } + /* XXX getting here means we probably have a bug... */ return (NULL); } @@ -247,7 +257,7 @@ _busdma_tag_get_base(device_t dev) base = busdma_root_tag; parent = NULL; } - _busdma_tag_dump(__func__, parent, base); + // _busdma_tag_dump(__func__, parent, base); return (base); } @@ -281,7 +291,7 @@ _busdma_tag_make(device_t dev, struct bu tag->dt_maxsz = MIN(maxsz, base->dt_maxsz); tag->dt_nsegs = MIN(nsegs, base->dt_nsegs); tag->dt_maxsegsz = MIN(maxsegsz, base->dt_maxsegsz); - _busdma_tag_dump(__func__, dev, tag); + // _busdma_tag_dump(__func__, dev, tag); *tag_p = tag; return (0); } @@ -313,12 +323,12 @@ _busdma_iommu_xlate(device_t leaf, struc error = 0; dev = device_get_parent(leaf); while (!error && dev != root_bus) { - _busdma_mtag_dump(__func__, dev, mtag); + // _busdma_mtag_dump(__func__, dev, mtag); error = BUSDMA_IOMMU_XLATE(dev, mtag); if (!error) dev = device_get_parent(dev); } - _busdma_mtag_dump(__func__, dev, mtag); + // _busdma_mtag_dump(__func__, dev, mtag); return (error); } @@ -351,7 +361,7 @@ _busdma_iommu_map(device_t leaf, struct device_t dev; int error; - _busdma_md_dump(__func__, root_bus, md); + // _busdma_md_dump(__func__, root_bus, md); dev = device_get_parent(leaf); error = 0; TAILQ_FOREACH(seg, &md->md_seg, mds_chain) { @@ -359,11 +369,62 @@ _busdma_iommu_map(device_t leaf, struct if (error) break; } - if (!error) - _busdma_md_dump(__func__, leaf, md); + if (!error) { + // _busdma_md_dump(__func__, leaf, md); + } return (error); } +static int +_busdma_md_load(struct busdma_md *md, pmap_t pm, vm_offset_t va, vm_size_t len) +{ + struct busdma_md_seg *seg; + vm_paddr_t pa; + vm_size_t catsz, maxsegsz, pgsz, sz; + u_int idx; + + maxsegsz = md->md_tag->dt_maxsegsz; + seg = TAILQ_LAST(&md->md_seg, busdma_md_head); + idx = (seg != NULL) ? seg->mds_idx + 1 : 0; + while (len != 0) { + pa = (pm != NULL) ? pmap_extract(pm, va) : pmap_kextract(va); + pgsz = PAGE_SIZE - (va & PAGE_MASK); + sz = MIN(len, maxsegsz); + sz = MIN(pgsz, sz); + if (seg != NULL && seg->mds_size < maxsegsz && + seg->mds_paddr + seg->mds_size == pa) { + catsz = maxsegsz - seg->mds_size; + catsz = MIN(sz, catsz); + seg->mds_size += catsz; + pa += catsz; + sz -= catsz; + va += catsz; + } + + if (sz == 0) + continue; + + /* + * The remaining sz bytes go in a new segment. + */ + seg = uma_zalloc(busdma_md_seg_zone, M_NOWAIT); + if (seg == NULL) + return (ENOMEM); + seg->mds_idx = idx++; + TAILQ_INSERT_TAIL(&md->md_seg, seg, mds_chain); + md->md_nsegs++; + seg->mds_busaddr = ~0U; + seg->mds_paddr = pa; + seg->mds_vaddr = 0; + seg->mds_size = sz; + len -= sz; + va += sz; + } + + // _busdma_md_dump(__func__, NULL, md); + return (0); +} + /* * Section 4: Public interface. */ @@ -376,6 +437,9 @@ busdma_tag_create(device_t dev, bus_addr struct busdma_tag *base, *first, *tag; int error; + if (dev == NULL || tag_p == NULL) + return (EINVAL); + base = _busdma_tag_get_base(dev); error = _busdma_tag_make(dev, base, align, bndry, maxaddr, maxsz, nsegs, maxsegsz, flags, &tag); @@ -399,6 +463,9 @@ busdma_tag_derive(struct busdma_tag *bas struct busdma_tag *tag; int error; + if (base == NULL || tag_p == NULL) + return (EINVAL); + error = _busdma_tag_make(base->dt_device, base, align, bndry, maxaddr, maxsz, nsegs, maxsegsz, flags, &tag); if (error != 0) @@ -418,6 +485,10 @@ int busdma_tag_destroy(struct busdma_tag *tag) { + if (tag == NULL) + return (EINVAL); + + /* TODO */ return (0); } @@ -426,11 +497,14 @@ busdma_md_create(struct busdma_tag *tag, { struct busdma_md *md; + if (tag == NULL || md_p == NULL) + return (EINVAL); + md = _busdma_md_create(tag, 0); if (md == NULL) return (ENOMEM); - _busdma_md_dump(__func__, NULL, md); + // _busdma_md_dump(__func__, NULL, md); *md_p = md; return (0); } @@ -439,6 +513,8 @@ int busdma_md_destroy(struct busdma_md *md) { + if (md == NULL) + return (EINVAL); if ((md->md_flags & BUSDMA_MD_FLAG_ALLOCATED) != 0) return (EINVAL); if (md->md_nsegs > 0) @@ -462,7 +538,7 @@ u_int busdma_md_get_nsegs(struct busdma_md *md) { - return (md->md_nsegs); + return ((md != NULL) ? md->md_nsegs : 0); } vm_paddr_t @@ -496,10 +572,21 @@ int busdma_md_load_linear(struct busdma_md *md, void *buf, size_t len, busdma_callback_f cb, void *arg, u_int flags) { + int error; - printf("XXX: %s: md=%p, buf=%p, len=%lx\n", __func__, md, - buf, (u_long)len); - (*cb)(arg, md, ENOSYS); + // printf("XXX: %s: md=%p, buf=%p, len=%lx\n", __func__, md, + // buf, (u_long)len); + + if (md == NULL || buf == NULL || len == 0) + return (EINVAL); + + error = _busdma_md_load(md, NULL, (uintptr_t)buf, len); + if (!error) { + error = _busdma_iommu_map(md->md_tag->dt_device, md); + if (error) + printf("_busdma_iommu_map: error=%d\n", error); + } + (*cb)(arg, md, error); return (0); } @@ -508,8 +595,8 @@ busdma_md_load_phys(struct busdma_md *md busdma_callback_f cb, void *arg, u_int flags) { - printf("XXX: %s: md=%p, buf=%#jx, len=%lx\n", __func__, md, - (uintmax_t)buf, (u_long)len); + // printf("XXX: %s: md=%p, buf=%#jx, len=%lx\n", __func__, md, + // (uintmax_t)buf, (u_long)len); (*cb)(arg, md, ENOSYS); return (0); } @@ -519,7 +606,7 @@ busdma_md_load_uio(struct busdma_md *md, busdma_callback_f cb, void *arg, u_int flags) { - printf("XXX: %s: md=%p, uio=%p\n", __func__, md, uio); + // printf("XXX: %s: md=%p, uio=%p\n", __func__, md, uio); (*cb)(arg, md, ENOSYS); return (0); } @@ -527,8 +614,32 @@ busdma_md_load_uio(struct busdma_md *md, int busdma_md_unload(struct busdma_md *md) { + struct busdma_md_seg *seg; + device_t bus; + int error; + + // printf("XXX: %s: md=%p\n", __func__, md); + + if (md == NULL) + return (EINVAL); + if ((md->md_flags & BUSDMA_MD_FLAG_ALLOCATED) != 0) + return (EINVAL); + + if (md->md_nsegs == 0) + return (0); + + bus = device_get_parent(md->md_tag->dt_device); + error = BUSDMA_IOMMU_UNMAP(bus, md); + if (error) + printf("BUSDMA_IOMMU_UNMAP: error=%d\n", error); + + while ((seg = TAILQ_FIRST(&md->md_seg)) != NULL) { + TAILQ_REMOVE(&md->md_seg, seg, mds_chain); + uma_zfree(busdma_md_seg_zone, seg); + } - return (ENOSYS); + md->md_nsegs = 0; + return (0); } int @@ -541,12 +652,13 @@ busdma_mem_alloc(struct busdma_tag *tag, u_int idx; int error; + if (tag == NULL || md_p == NULL) + return (EINVAL); + md = _busdma_md_create(tag, BUSDMA_MD_FLAG_ALLOCATED); if (md == NULL) return (ENOMEM); - idx = 0; - mtag.dmt_minaddr = tag->dt_minaddr; mtag.dmt_maxaddr = tag->dt_maxaddr; mtag.dmt_maxsz = tag->dt_maxsegsz; @@ -559,6 +671,7 @@ busdma_mem_alloc(struct busdma_tag *tag, goto fail; } + idx = 0; maxsz = tag->dt_maxsz; while (maxsz > 0 && idx < tag->dt_nsegs) { seg = uma_zalloc(busdma_md_seg_zone, M_NOWAIT); @@ -566,6 +679,7 @@ busdma_mem_alloc(struct busdma_tag *tag, goto fail; seg->mds_idx = idx; TAILQ_INSERT_TAIL(&md->md_seg, seg, mds_chain); + md->md_nsegs++; seg->mds_busaddr = ~0UL; seg->mds_paddr = ~0UL; seg->mds_size = MIN(maxsz, mtag.dmt_maxsz); @@ -581,7 +695,6 @@ busdma_mem_alloc(struct busdma_tag *tag, idx++; } if (maxsz == 0) { - md->md_nsegs = idx; error = _busdma_iommu_map(tag->dt_device, md); if (error) printf("_busdma_iommu_map: error=%d\n", error); @@ -607,6 +720,8 @@ busdma_mem_free(struct busdma_md *md) device_t bus; int error; + if (md == NULL) + return (EINVAL); if ((md->md_flags & BUSDMA_MD_FLAG_ALLOCATED) == 0) return (EINVAL);