Date: Thu, 30 Oct 2014 11:27:03 +0000 (UTC) From: Tijl Coosemans <tijl@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r273856 - head/sys/dev/agp Message-ID: <201410301127.s9UBR3Rn069564@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: tijl Date: Thu Oct 30 11:27:03 2014 New Revision: 273856 URL: https://svnweb.freebsd.org/changeset/base/273856 Log: Add two new functions to the AGP driver KPI to bind/unbind arbitrary sets of pages into the GTT. Reviewed by: kib MFC after: 1 month Modified: head/sys/dev/agp/agp.c head/sys/dev/agp/agpvar.h Modified: head/sys/dev/agp/agp.c ============================================================================== --- head/sys/dev/agp/agp.c Thu Oct 30 10:59:57 2014 (r273855) +++ head/sys/dev/agp/agp.c Thu Oct 30 11:27:03 2014 (r273856) @@ -996,3 +996,76 @@ void agp_memory_info(device_t dev, void mi->ami_offset = mem->am_offset; mi->ami_is_bound = mem->am_is_bound; } + +int +agp_bind_pages(device_t dev, vm_page_t *pages, vm_size_t size, + vm_offset_t offset) +{ + struct agp_softc *sc; + vm_offset_t i, j, k, pa; + vm_page_t m; + int error; + + if ((size & (AGP_PAGE_SIZE - 1)) != 0 || + (offset & (AGP_PAGE_SIZE - 1)) != 0) + return (EINVAL); + + sc = device_get_softc(dev); + + mtx_lock(&sc->as_lock); + for (i = 0; i < size; i += PAGE_SIZE) { + m = pages[OFF_TO_IDX(i)]; + + /* + * Install entries in the GATT, making sure that if + * AGP_PAGE_SIZE < PAGE_SIZE and size is not + * aligned to PAGE_SIZE, we don't modify too many GATT + * entries. + */ + for (j = 0; j < PAGE_SIZE && i + j < size; j += AGP_PAGE_SIZE) { + pa = VM_PAGE_TO_PHYS(m) + j; + AGP_DPF("binding offset %#jx to pa %#jx\n", + (uintmax_t)offset + i + j, (uintmax_t)pa); + error = AGP_BIND_PAGE(dev, offset + i + j, pa); + if (error) { + /* + * Bail out. Reverse all the mappings. + */ + for (k = 0; k < i + j; k += AGP_PAGE_SIZE) + AGP_UNBIND_PAGE(dev, offset + k); + + mtx_unlock(&sc->as_lock); + return (error); + } + } + } + + agp_flush_cache(); + AGP_FLUSH_TLB(dev); + + mtx_unlock(&sc->as_lock); + return (0); +} + +int +agp_unbind_pages(device_t dev, vm_size_t size, vm_offset_t offset) +{ + struct agp_softc *sc; + vm_offset_t i; + + if ((size & (AGP_PAGE_SIZE - 1)) != 0 || + (offset & (AGP_PAGE_SIZE - 1)) != 0) + return (EINVAL); + + sc = device_get_softc(dev); + + mtx_lock(&sc->as_lock); + for (i = 0; i < size; i += AGP_PAGE_SIZE) + AGP_UNBIND_PAGE(dev, offset + i); + + agp_flush_cache(); + AGP_FLUSH_TLB(dev); + + mtx_unlock(&sc->as_lock); + return (0); +} Modified: head/sys/dev/agp/agpvar.h ============================================================================== --- head/sys/dev/agp/agpvar.h Thu Oct 30 10:59:57 2014 (r273855) +++ head/sys/dev/agp/agpvar.h Thu Oct 30 11:27:03 2014 (r273856) @@ -122,6 +122,19 @@ int agp_unbind_memory(device_t dev, void */ void agp_memory_info(device_t dev, void *handle, struct agp_memory_info *mi); +/* + * Bind a set of pages at a given offset within the AGP aperture. + * Returns EINVAL if the given size or offset is not at an AGP page boundary. + */ +int agp_bind_pages(device_t dev, vm_page_t *pages, vm_size_t size, + vm_offset_t offset); + +/* + * Unbind a set of pages from the AGP aperture. + * Returns EINVAL if the given size or offset is not at an AGP page boundary. + */ +int agp_unbind_pages(device_t dev, vm_size_t size, vm_offset_t offset); + #define AGP_NORMAL_MEMORY 0 #define AGP_USER_TYPES (1 << 16)
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201410301127.s9UBR3Rn069564>