diff options
| author | bjs <bjs@NetBSD.org> | 2008-06-20 00:14:28 +0000 |
|---|---|---|
| committer | bjs <bjs@NetBSD.org> | 2008-06-20 00:14:28 +0000 |
| commit | 6c1a2fee8fb51164b08f567435e20dc1bb290d26 (patch) | |
| tree | 9cd75fc7f6d250aa1c96a35d4d62757a43a9efb1 /sys/dev | |
| parent | 4537375adaf1705a195eccceffff47ec5dd39d85 (diff) | |
- Use the extent manager to track mappings and provide sane offset
"cookies" for mmap. Now the radeon driver works on amd64!
- Use bus_dma for nearly all map types (carried over from prior patch).
- Plug some lock leaks in drm_bufs.c and remove superfluous locking in
drm_add_magic() (from git).
- Lower spl of mutexes to IPL_NONE (and so are now adaptive instead of
spin mutexes), save for irq_lock which is a spin mutex at IPL_VM.
Use mutex_spin_enter()/mutex_spin_exit() for irq_lock.
ok jmcneill@
Diffstat (limited to 'sys/dev')
| -rw-r--r-- | sys/dev/drm/drmP.h | 54 | ||||
| -rw-r--r-- | sys/dev/drm/drm_auth.c | 6 | ||||
| -rw-r--r-- | sys/dev/drm/drm_bufs.c | 59 | ||||
| -rw-r--r-- | sys/dev/drm/drm_drv.c | 8 | ||||
| -rw-r--r-- | sys/dev/drm/drm_irq.c | 18 | ||||
| -rw-r--r-- | sys/dev/drm/drm_memory.c | 19 | ||||
| -rw-r--r-- | sys/dev/drm/drm_pci.c | 58 | ||||
| -rw-r--r-- | sys/dev/drm/drm_scatter.c | 45 | ||||
| -rw-r--r-- | sys/dev/drm/drm_vm.c | 34 | ||||
| -rw-r--r-- | sys/dev/drm/files.drm | 3 |
10 files changed, 174 insertions, 130 deletions
diff --git a/sys/dev/drm/drmP.h b/sys/dev/drm/drmP.h index b98a581ba81..1945c18fe74 100644 --- a/sys/dev/drm/drmP.h +++ b/sys/dev/drm/drmP.h @@ -1,4 +1,4 @@ -/* $NetBSD: drmP.h,v 1.28 2008/06/09 06:49:55 freza Exp $ */ +/* $NetBSD: drmP.h,v 1.29 2008/06/20 00:14:28 bjs Exp $ */ /* drmP.h -- Private header for Direct Rendering Manager -*- linux-c -*- * Created: Mon Jan 4 10:05:05 1999 by faith@precisioninsight.com @@ -59,6 +59,7 @@ typedef struct drm_file drm_file_t; #include <sys/param.h> #include <sys/queue.h> #include <sys/malloc.h> +#include <sys/extent.h> #include <sys/kernel.h> #ifdef __FreeBSD__ #include <sys/module.h> @@ -136,6 +137,7 @@ typedef struct drm_file drm_file_t; #include "drm.h" #include "drm_linux_list.h" #include "drm_atomic.h" +#include "drm_netbsd.h" #if defined(__FreeBSD__) || defined(__NetBSD__) #if defined(_KERNEL_OPT) @@ -238,13 +240,17 @@ MALLOC_DECLARE(M_DRM); #define DRM_STRUCTPROC struct proc #define DRM_STRUCTCDEVPROC struct lwp #define DRM_SPINTYPE kmutex_t -#define DRM_SPININIT(l,name) mutex_init(l, MUTEX_DEFAULT, IPL_VM) +#define DRM_SPININIT(l,name) mutex_init(l, MUTEX_DEFAULT, IPL_NONE) #define DRM_SPINUNINIT(l) mutex_destroy(l) #define DRM_SPINLOCK(l) mutex_enter(l) #define DRM_SPINUNLOCK(u) mutex_exit(u) -#define DRM_SPINLOCK_ASSERT(l) mutex_owned(l) -#define DRM_LOCK() DRM_SPINLOCK(&dev->dev_lock) -#define DRM_UNLOCK() DRM_SPINUNLOCK(&dev->dev_lock) +#ifdef LOCKDEBUG +#define DRM_SPINLOCK_ASSERT(l) KASSERT(mutex_owned(l)) +#else +#define DRM_SPINLOCK_ASSERT(l) do {} while (0) +#endif +#define DRM_LOCK() mutex_enter(&dev->dev_lock) +#define DRM_UNLOCK() mutex_exit(&dev->dev_lock) #define DRM_CURRENTPID curproc->p_pid #define DRM_SYSCTL_HANDLER_ARGS (SYSCTLFN_ARGS) #else @@ -515,11 +521,11 @@ for ( ret = 0 ; !ret && !(condition) ; ) { \ #define DRM_WAIT_ON( ret, queue, timeout, condition ) \ for ( ret = 0 ; !ret && !(condition) ; ) { \ DRM_UNLOCK(); \ - mutex_enter(&dev->irq_lock); \ + mutex_spin_enter(&dev->irq_lock); \ if (!(condition)) \ ret = mtsleep(&(queue), PZERO | PCATCH, \ "drmwtq", (timeout), &dev->irq_lock); \ - mutex_exit(&dev->irq_lock); \ + mutex_spin_exit(&dev->irq_lock); \ DRM_LOCK(); \ } #else @@ -614,13 +620,10 @@ typedef struct drm_freelist { typedef struct drm_dma_handle { void *vaddr; bus_addr_t busaddr; - bus_dma_tag_t dmat; - bus_dmamap_t map; - bus_dma_segment_t segs[1]; + size_t size; - void *addr; + struct drm_dmamem *mem; } drm_dma_handle_t; -#define DRM_PCI_DMAADDR(p) ((p)->map->dm_segs[0].ds_addr) typedef struct drm_buf_entry { int buf_size; @@ -702,7 +705,11 @@ typedef struct drm_sg_mem { void *virtual; int pages; dma_addr_t *busaddr; - drm_dma_handle_t *dmah; /* Handle to PCI memory for ATI PCIGART table */ +/* + * Handle to PCI memory for GART table + */ + drm_dma_handle_t *dmah; + struct drm_dmamem *mem; } drm_sg_mem_t; typedef TAILQ_HEAD(drm_map_list, drm_local_map) drm_map_list_t; @@ -726,6 +733,8 @@ typedef struct drm_local_map { #ifdef __NetBSD__ int *cnt; bus_size_t mapsize; + u_long cookie; /* mmap cookie */ + struct drm_dmamem *mem; #endif TAILQ_ENTRY(drm_local_map) link; } drm_local_map_t; @@ -934,6 +943,10 @@ struct drm_device { void *dev_private; unsigned int agp_buffer_token; drm_local_map_t *agp_buffer_map; + +#if defined(__NetBSD__) + struct extent *ex; /* Extent map for mmap cookies */ +#endif }; extern int drm_debug_flag; @@ -979,8 +992,14 @@ extern drm_file_t *drm_find_file_by_proc(drm_device_t *dev, #endif /* __NetBSD__ || __OpenBSD__ */ /* Memory management support (drm_memory.c) */ -void drm_mem_init(void); -void drm_mem_uninit(void); + +/* + * XXX The drm_mem_init/uninit functions originally took void arguments. + * However, these are sensible places to create/destroy the mmap cookie + * extent map, and so they now take a pointer to the "drm device". + */ +void drm_mem_init(struct drm_device *); +void drm_mem_uninit(struct drm_device *); void *drm_alloc(size_t size, int area); void *drm_calloc(size_t nmemb, size_t size, int area); void *drm_realloc(void *oldpt, size_t oldsize, size_t size, @@ -1154,9 +1173,12 @@ static __inline__ struct drm_local_map *drm_core_findmap(struct drm_device *dev, { drm_local_map_t *map; + /* NOTE: this code must be remain in harmony with related code + * in drm_mmap(), drm_addmap_ioctl(), and/or drm_rmmap(). + */ DRM_SPINLOCK_ASSERT(&dev->dev_lock); TAILQ_FOREACH(map, &dev->maplist, link) { - if (map->offset == offset) + if (map->cookie == offset) return map; } return NULL; diff --git a/sys/dev/drm/drm_auth.c b/sys/dev/drm/drm_auth.c index 801e45e2d70..6c2c5bd0b6a 100644 --- a/sys/dev/drm/drm_auth.c +++ b/sys/dev/drm/drm_auth.c @@ -1,4 +1,4 @@ -/* $NetBSD: drm_auth.c,v 1.4 2007/12/11 11:17:31 lukem Exp $ */ +/* $NetBSD: drm_auth.c,v 1.5 2008/06/20 00:14:28 bjs Exp $ */ /* drm_auth.h -- IOCTLs for authentication -*- linux-c -*- * Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com @@ -34,7 +34,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: drm_auth.c,v 1.4 2007/12/11 11:17:31 lukem Exp $"); +__KERNEL_RCSID(0, "$NetBSD: drm_auth.c,v 1.5 2008/06/20 00:14:28 bjs Exp $"); /* __FBSDID("$FreeBSD: src/sys/dev/drm/drm_auth.c,v 1.2 2005/11/28 23:13:52 anholt Exp $"); */ @@ -79,7 +79,6 @@ static int drm_add_magic(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic) entry->priv = priv; entry->next = NULL; - DRM_LOCK(); if (dev->magiclist[hash].tail) { dev->magiclist[hash].tail->next = entry; dev->magiclist[hash].tail = entry; @@ -87,7 +86,6 @@ static int drm_add_magic(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic) dev->magiclist[hash].head = entry; dev->magiclist[hash].tail = entry; } - DRM_UNLOCK(); return 0; } diff --git a/sys/dev/drm/drm_bufs.c b/sys/dev/drm/drm_bufs.c index fc852b0d27f..1eb4be15cfc 100644 --- a/sys/dev/drm/drm_bufs.c +++ b/sys/dev/drm/drm_bufs.c @@ -1,4 +1,4 @@ -/* $NetBSD: drm_bufs.c,v 1.7 2008/05/04 20:09:32 jmcneill Exp $ */ +/* $NetBSD: drm_bufs.c,v 1.8 2008/06/20 00:14:28 bjs Exp $ */ /* drm_bufs.h -- Generic buffer template -*- linux-c -*- * Created: Thu Nov 23 03:10:50 2000 by gareth@valinux.com @@ -34,7 +34,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: drm_bufs.c,v 1.7 2008/05/04 20:09:32 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: drm_bufs.c,v 1.8 2008/06/20 00:14:28 bjs Exp $"); /* __FBSDID("$FreeBSD: src/sys/dev/drm/drm_bufs.c,v 1.3 2005/11/28 23:13:52 anholt Exp $"); */ @@ -139,8 +139,10 @@ int drm_addmap(drm_device_t * dev, unsigned long offset, unsigned long size, * initialization necessary. */ map = malloc(sizeof(*map), M_DRM, M_ZERO | M_NOWAIT); - if ( !map ) + if ( !map ) { + DRM_LOCK(); return DRM_ERR(ENOMEM); + } map->offset = offset; map->size = size; @@ -148,6 +150,20 @@ int drm_addmap(drm_device_t * dev, unsigned long offset, unsigned long size, map->flags = flags; map->cnt = NULL; /* cnt, mapsize added for NetBSD port */ map->mapsize = 0; + map->cookie = 0; + + /* XXX We're not managing any actual address space here; we simply + * need to assign unique and sane cookies as to not offend + * the device pager. + */ + extent_alloc(dev->ex, map->size, PAGE_SIZE, 0, EX_FAST|EX_WAITOK, + &map->cookie); + if (map->cookie == 0) { + DRM_DEBUG("could not allocate entry for mmap cookie in extent map!\n"); + free(map, M_DRM); + DRM_LOCK(); + return DRM_ERR(ENOMEM); + } switch ( map->type ) { case _DRM_REGISTERS: @@ -162,20 +178,22 @@ int drm_addmap(drm_device_t * dev, unsigned long offset, unsigned long size, #endif break; case _DRM_SHM: - map->handle = malloc(map->size, M_DRM, M_NOWAIT); + map->mem = drm_dmamem_pgalloc(dev, btop(map->size)); DRM_DEBUG( "%lu %d %p\n", map->size, drm_order(map->size), map->handle ); - if ( !map->handle ) { + if ( map->mem == NULL ) { free(map, M_DRM); + DRM_LOCK(); return DRM_ERR(ENOMEM); } - map->offset = (unsigned long)map->handle; + map->handle = map->mem->dd_kva; + map->offset = map->mem->dd_dmam->dm_segs[0].ds_addr; if ( map->flags & _DRM_CONTAINS_LOCK ) { /* Prevent a 2nd X Server from creating a 2nd lock */ DRM_LOCK(); if (dev->lock.hw_lock != NULL) { DRM_UNLOCK(); - free(map->handle, M_DRM); + drm_dmamem_free(map->mem); free(map, M_DRM); return DRM_ERR(EBUSY); } @@ -197,15 +215,18 @@ int drm_addmap(drm_device_t * dev, unsigned long offset, unsigned long size, } if (!valid) { free(map, M_DRM); + DRM_LOCK(); return DRM_ERR(EACCES); }*/ break; case _DRM_SCATTER_GATHER: if (!dev->sg) { free(map, M_DRM); + DRM_LOCK(); return DRM_ERR(EINVAL); } map->offset = map->offset + dev->sg->handle; + map->mem = dev->sg->mem; break; case _DRM_CONSISTENT: /* Unfortunately, we don't get any alignment specification from @@ -220,14 +241,17 @@ int drm_addmap(drm_device_t * dev, unsigned long offset, unsigned long size, map->dmah = drm_pci_alloc(dev, map->size, align, 0xfffffffful); if (map->dmah == NULL) { free(map, M_DRM); + DRM_LOCK(); return DRM_ERR(ENOMEM); } map->handle = map->dmah->vaddr; map->offset = map->dmah->busaddr; + map->mem = map->dmah->mem; break; default: DRM_ERROR("Bad map type %d\n", map->type); free(map, M_DRM); + DRM_LOCK(); return DRM_ERR(EINVAL); } @@ -274,8 +298,11 @@ int drm_addmap_ioctl(DRM_IOCTL_ARGS) request.mtrr = map->mtrr; request.handle = map->handle; + /* NOTE: ensure this code harmonizes with drm_core_findmap(), + * drm_mmap(), and/or drm_rmmap(). + */ if (request.type != _DRM_SHM) { - request.handle = (void *)request.offset; + request.handle = (void *)map->cookie; } else { request.handle = (void *)DRM_NETBSD_ADDR2HANDLE((uintptr_t)map->handle); } @@ -304,7 +331,7 @@ void drm_rmmap(drm_device_t *dev, drm_local_map_t *map) #endif break; case _DRM_SHM: - free(map->handle, M_DRM); + drm_dmamem_free(map->mem); break; case _DRM_AGP: case _DRM_SCATTER_GATHER: @@ -314,6 +341,8 @@ void drm_rmmap(drm_device_t *dev, drm_local_map_t *map) break; } + extent_free(dev->ex, map->cookie, map->size, EX_WAITOK); + TAILQ_REMOVE(&dev->maplist, map, link); free(map, M_DRM); } @@ -771,7 +800,6 @@ int drm_addbufs_agp(drm_device_t *dev, drm_buf_desc_t *request) { int order, ret; - DRM_SPINLOCK(&dev->dma_lock); if (request->count < 0 || request->count > 4096) return DRM_ERR(EINVAL); @@ -780,6 +808,8 @@ int drm_addbufs_agp(drm_device_t *dev, drm_buf_desc_t *request) if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return DRM_ERR(EINVAL); + DRM_SPINLOCK(&dev->dma_lock); + /* No more allocations after first buffer-using ioctl. */ if (dev->buf_use != 0) { DRM_SPINUNLOCK(&dev->dma_lock); @@ -802,7 +832,6 @@ int drm_addbufs_sg(drm_device_t *dev, drm_buf_desc_t *request) { int order, ret; - DRM_SPINLOCK(&dev->dma_lock); if (!DRM_SUSER(DRM_CURPROC)) return DRM_ERR(EACCES); @@ -814,6 +843,8 @@ int drm_addbufs_sg(drm_device_t *dev, drm_buf_desc_t *request) if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return DRM_ERR(EINVAL); + DRM_SPINLOCK(&dev->dma_lock); + /* No more allocations after first buffer-using ioctl. */ if (dev->buf_use != 0) { DRM_SPINUNLOCK(&dev->dma_lock); @@ -836,7 +867,6 @@ int drm_addbufs_pci(drm_device_t *dev, drm_buf_desc_t *request) { int order, ret; - DRM_SPINLOCK(&dev->dma_lock); if (!DRM_SUSER(DRM_CURPROC)) return DRM_ERR(EACCES); @@ -848,6 +878,8 @@ int drm_addbufs_pci(drm_device_t *dev, drm_buf_desc_t *request) if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return DRM_ERR(EINVAL); + DRM_SPINLOCK(&dev->dma_lock); + /* No more allocations after first buffer-using ioctl. */ if (dev->buf_use != 0) { DRM_SPINUNLOCK(&dev->dma_lock); @@ -1052,8 +1084,9 @@ int drm_mapbufs(DRM_IOCTL_ARGS) retcode = EINVAL; goto done; } + /* XXX using cookie, not actual offset here */ size = round_page(map->size); - foff = map->offset; + foff = map->cookie; } else { size = round_page(dma->byte_count), foff = 0; diff --git a/sys/dev/drm/drm_drv.c b/sys/dev/drm/drm_drv.c index 7d09b50be20..35b41f63785 100644 --- a/sys/dev/drm/drm_drv.c +++ b/sys/dev/drm/drm_drv.c @@ -1,4 +1,4 @@ -/* $NetBSD: drm_drv.c,v 1.16 2008/05/30 11:26:21 jmcneill Exp $ */ +/* $NetBSD: drm_drv.c,v 1.17 2008/06/20 00:14:28 bjs Exp $ */ /* drm_drv.h -- Generic driver template -*- linux-c -*- * Created: Thu Nov 23 03:10:50 2000 by gareth@valinux.com @@ -34,7 +34,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: drm_drv.c,v 1.16 2008/05/30 11:26:21 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: drm_drv.c,v 1.17 2008/06/20 00:14:28 bjs Exp $"); /* __FBSDID("$FreeBSD: src/sys/dev/drm/drm_drv.c,v 1.6 2006/09/07 23:04:47 anholt Exp $"); */ @@ -451,7 +451,7 @@ static int drm_load(drm_device_t *dev) TAILQ_INIT(&dev->maplist); - drm_mem_init(); + drm_mem_init(dev); drm_sysctl_init(dev); TAILQ_INIT(&dev->files); @@ -552,7 +552,7 @@ static void drm_unload(drm_device_t *dev) if (dev->driver.unload != NULL) dev->driver.unload(dev); - drm_mem_uninit(); + drm_mem_uninit(dev); DRM_SPINUNINIT(&dev->dev_lock); } diff --git a/sys/dev/drm/drm_irq.c b/sys/dev/drm/drm_irq.c index ce04502c7a6..453ef1137f1 100644 --- a/sys/dev/drm/drm_irq.c +++ b/sys/dev/drm/drm_irq.c @@ -1,4 +1,4 @@ -/* $NetBSD: drm_irq.c,v 1.12 2008/05/19 00:17:39 bjs Exp $ */ +/* $NetBSD: drm_irq.c,v 1.13 2008/06/20 00:14:28 bjs Exp $ */ /* drm_irq.c -- IRQ IOCTL and function support * Created: Fri Oct 18 2003 by anholt@FreeBSD.org @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: drm_irq.c,v 1.12 2008/05/19 00:17:39 bjs Exp $"); +__KERNEL_RCSID(0, "$NetBSD: drm_irq.c,v 1.13 2008/06/20 00:14:28 bjs Exp $"); /* __FBSDID("$FreeBSD: src/sys/dev/drm/drm_irq.c,v 1.2 2005/11/28 23:13:52 anholt Exp $"); */ @@ -68,9 +68,9 @@ drm_irq_handler_wrap(DRM_IRQ_ARGS) irqreturn_t ret; drm_device_t *dev = (drm_device_t *)arg; - DRM_SPINLOCK(&dev->irq_lock); + mutex_spin_enter(&dev->irq_lock); ret = dev->driver.irq_handler(arg); - DRM_SPINUNLOCK(&dev->irq_lock); + mutex_spin_exit(&dev->irq_lock); return ret; } @@ -94,7 +94,7 @@ int drm_irq_install(drm_device_t *dev) dev->context_flag = 0; - DRM_SPININIT(&dev->irq_lock, "DRM IRQ lock"); + mutex_init(&dev->irq_lock, MUTEX_SPIN, IPL_VM); /* Before installing handler */ @@ -124,7 +124,7 @@ int drm_irq_install(drm_device_t *dev) err: DRM_LOCK(); dev->irq_enabled = 0; - DRM_SPINUNINIT(&dev->irq_lock); + mutex_destroy(&dev->irq_lock); DRM_UNLOCK(); return retcode; } @@ -141,7 +141,7 @@ int drm_irq_uninstall(drm_device_t *dev) dev->driver.irq_uninstall(dev); pci_intr_disestablish(dev->pa.pa_pc, dev->irqh); - DRM_SPINUNINIT(&dev->irq_lock); + mutex_destroy(&dev->irq_lock); return 0; } @@ -209,9 +209,9 @@ int drm_wait_vblank(DRM_IOCTL_ARGS) vblwait.reply.sequence = atomic_read(&dev->vbl_received); - DRM_SPINLOCK(&dev->irq_lock); + mutex_spin_enter(&dev->irq_lock); TAILQ_INSERT_HEAD(&dev->vbl_sig_list, vbl_sig, link); - DRM_SPINUNLOCK(&dev->irq_lock); + mutex_spin_exit(&dev->irq_lock); ret = 0; #endif ret = EINVAL; diff --git a/sys/dev/drm/drm_memory.c b/sys/dev/drm/drm_memory.c index d75d153db92..6e9920c7c32 100644 --- a/sys/dev/drm/drm_memory.c +++ b/sys/dev/drm/drm_memory.c @@ -1,4 +1,4 @@ -/* $NetBSD: drm_memory.c,v 1.12 2008/05/19 21:05:37 jmcneill Exp $ */ +/* $NetBSD: drm_memory.c,v 1.13 2008/06/20 00:14:28 bjs Exp $ */ /* drm_memory.h -- Memory management wrappers for DRM -*- linux-c -*- * Created: Thu Feb 4 14:00:34 1999 by faith@valinux.com @@ -34,7 +34,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: drm_memory.c,v 1.12 2008/05/19 21:05:37 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: drm_memory.c,v 1.13 2008/06/20 00:14:28 bjs Exp $"); /* __FBSDID("$FreeBSD: src/sys/dev/drm/drm_memory.c,v 1.2 2005/11/28 23:13:52 anholt Exp $"); */ @@ -58,20 +58,23 @@ __FBSDID("$FreeBSD: src/sys/dev/drm/drm_memory.c,v 1.2 2005/11/28 23:13:52 anhol MALLOC_DEFINE(M_DRM, "drm", "DRM Data Structures"); #endif -void drm_mem_init(void) +void drm_mem_init(struct drm_device *dev) { -/* - malloc_type_attach(M_DRM); -*/ + + dev->ex = extent_create("drm", 0x00000000, 0x40000000, + M_DRM, NULL, 0, EX_NOWAIT); + if (dev->ex == NULL) + DRM_DEBUG("could not create extent map!\n"); } -void drm_mem_uninit(void) +void drm_mem_uninit(struct drm_device *dev) { + extent_destroy(dev->ex); } void *drm_alloc(size_t size, int area) { - return malloc(size, M_DRM, M_NOWAIT); + return malloc(1 * size, M_DRM, M_NOWAIT); } void *drm_calloc(size_t nmemb, size_t size, int area) diff --git a/sys/dev/drm/drm_pci.c b/sys/dev/drm/drm_pci.c index 63a2de5160d..8e8129a8ded 100644 --- a/sys/dev/drm/drm_pci.c +++ b/sys/dev/drm/drm_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: drm_pci.c,v 1.10 2008/05/06 01:45:47 bjs Exp $ */ +/* $NetBSD: drm_pci.c,v 1.11 2008/06/20 00:14:28 bjs Exp $ */ /* * Copyright 2003 Eric Anholt. @@ -24,7 +24,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: drm_pci.c,v 1.10 2008/05/06 01:45:47 bjs Exp $"); +__KERNEL_RCSID(0, "$NetBSD: drm_pci.c,v 1.11 2008/06/20 00:14:28 bjs Exp $"); /* __FBSDID("$FreeBSD: src/sys/dev/drm/drm_pci.c,v 1.2 2005/11/28 23:13:52 anholt Exp $"); */ @@ -35,55 +35,22 @@ drm_dma_handle_t * drm_pci_alloc(drm_device_t *dev, size_t size, size_t align, dma_addr_t maxaddr) { drm_dma_handle_t *h; - int error, nsegs; - - - /* Need power-of-two alignment, so fail the allocation if it isn't. */ - if ((align & (align - 1)) != 0) { - DRM_ERROR("drm_pci_alloc with non-power-of-two alignment %d\n", - (int)align); - return NULL; - } h = malloc(sizeof(drm_dma_handle_t), M_DRM, M_ZERO | M_NOWAIT); if (h == NULL) return NULL; - if ((error = bus_dmamem_alloc(dev->pa.pa_dmat, size, align, 0, - h->segs, 1, &nsegs, BUS_DMA_NOWAIT)) != 0) { - printf("drm: Unable to allocate DMA, error %d\n", error); - goto fail; - } - if ((error = bus_dmamem_map(dev->pa.pa_dmat, h->segs, nsegs, size, - &h->addr, BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) { - printf("drm: Unable to map DMA, error %d\n", error); - goto free; - } - if ((error = bus_dmamap_create(dev->pa.pa_dmat, size, 1, size, 0, - BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &h->map)) != 0) { - printf("drm: Unable to create DMA map, error %d\n", error); - goto unmap; - } - if ((error = bus_dmamap_load(dev->pa.pa_dmat, h->map, h->addr, size, - NULL, BUS_DMA_NOWAIT)) != 0) { - printf("drm: Unable to load DMA map, error %d\n", error); - goto destroy; - } - h->busaddr = DRM_PCI_DMAADDR(h); - h->vaddr = h->addr; - h->size = size; - - return h; -destroy: - bus_dmamap_destroy(dev->pa.pa_dmat, h->map); -unmap: - bus_dmamem_unmap(dev->pa.pa_dmat, h->addr, size); -free: - bus_dmamem_free(dev->pa.pa_dmat, h->segs, 1); -fail: + h->mem = drm_dmamem_pgalloc(dev, round_page(btop(size))); + if (h->mem == NULL) { free(h, M_DRM); return NULL; + } + + h->busaddr = DRM_DMAMEM_BUSADDR(h->mem); + h->vaddr = DRM_DMAMEM_KERNADDR(h->mem); + + return h; } @@ -96,10 +63,7 @@ drm_pci_free(drm_device_t *dev, drm_dma_handle_t *h) { if (h == NULL) return; - bus_dmamap_unload(dev->pa.pa_dmat, h->map); - bus_dmamap_destroy(dev->pa.pa_dmat, h->map); - bus_dmamem_unmap(dev->pa.pa_dmat, h->addr, h->size); - bus_dmamem_free(dev->pa.pa_dmat, h->segs, 1); + drm_dmamem_free(h->mem); free(h, M_DRM); } diff --git a/sys/dev/drm/drm_scatter.c b/sys/dev/drm/drm_scatter.c index 1ebca23ebc8..b9f52e42506 100644 --- a/sys/dev/drm/drm_scatter.c +++ b/sys/dev/drm/drm_scatter.c @@ -1,4 +1,4 @@ -/* $NetBSD: drm_scatter.c,v 1.4 2007/12/15 00:39:26 perry Exp $ */ +/* $NetBSD: drm_scatter.c,v 1.5 2008/06/20 00:14:28 bjs Exp $ */ /* drm_scatter.h -- IOCTLs to manage scatter/gather memory -*- linux-c -*- * Created: Mon Dec 18 23:20:54 2000 by gareth@valinux.com */ @@ -32,7 +32,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: drm_scatter.c,v 1.4 2007/12/15 00:39:26 perry Exp $"); +__KERNEL_RCSID(0, "$NetBSD: drm_scatter.c,v 1.5 2008/06/20 00:14:28 bjs Exp $"); /* __FBSDID("$FreeBSD: src/sys/dev/drm/drm_scatter.c,v 1.3 2006/05/17 06:29:36 anholt Exp $"); */ @@ -41,23 +41,27 @@ __FBSDID("$FreeBSD: src/sys/dev/drm/drm_scatter.c,v 1.3 2006/05/17 06:29:36 anho #define DEBUG_SCATTER 0 -void drm_sg_cleanup(drm_sg_mem_t *entry) +void +drm_sg_cleanup(drm_sg_mem_t *entry) { - free((void *)entry->handle, M_DRM); + if (entry) { + if (entry->mem) + drm_dmamem_free(entry->mem); + if (entry->busaddr) free(entry->busaddr, M_DRM); free(entry, M_DRM); } +} -int drm_sg_alloc(DRM_IOCTL_ARGS) +int +drm_sg_alloc(DRM_IOCTL_ARGS) { DRM_DEVICE; - drm_scatter_gather_t request; drm_sg_mem_t *entry; + drm_scatter_gather_t request; unsigned long pages; int i; - DRM_DEBUG( "%s\n", __func__ ); - if ( dev->sg ) return EINVAL; @@ -80,17 +84,23 @@ int drm_sg_alloc(DRM_IOCTL_ARGS) return ENOMEM; } - entry->handle = (long)malloc(pages << PAGE_SHIFT, M_DRM, - M_WAITOK | M_ZERO); - if (entry->handle == 0) { + if ((entry->mem = drm_dmamem_pgalloc(dev, pages)) == NULL) { drm_sg_cleanup(entry); return ENOMEM; } - for (i = 0; i < pages; i++) { - entry->busaddr[i] = vtophys(entry->handle + i * PAGE_SIZE); + entry->handle = (unsigned long)entry->mem->dd_kva; + + if (pages != entry->mem->dd_dmam->dm_nsegs) { + DRM_DEBUG("pages (%ld) != nsegs (%i)\n", pages, + entry->mem->dd_dmam->dm_nsegs); + drm_sg_cleanup(entry); + return ENOMEM; } + for (i = 0; i < pages; i++) + entry->busaddr[i] = entry->mem->dd_dmam->dm_segs[i].ds_addr; + DRM_DEBUG( "sg alloc handle = %08lx\n", entry->handle ); entry->virtual = (void *)entry->handle; @@ -112,20 +122,21 @@ int drm_sg_alloc(DRM_IOCTL_ARGS) return 0; } -int drm_sg_free(DRM_IOCTL_ARGS) +int +drm_sg_free(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_scatter_gather_t request; drm_sg_mem_t *entry; - DRM_COPY_FROM_USER_IOCTL( request, (drm_scatter_gather_t *)data, - sizeof(request) ); - DRM_LOCK(); entry = dev->sg; dev->sg = NULL; DRM_UNLOCK(); + DRM_COPY_FROM_USER_IOCTL( request, (drm_scatter_gather_t *)data, + sizeof(request) ); + if ( !entry || entry->handle != request.handle ) return EINVAL; diff --git a/sys/dev/drm/drm_vm.c b/sys/dev/drm/drm_vm.c index 64e20ab8fb3..ad879d15093 100644 --- a/sys/dev/drm/drm_vm.c +++ b/sys/dev/drm/drm_vm.c @@ -1,4 +1,4 @@ -/* $NetBSD: drm_vm.c,v 1.10 2008/05/04 21:43:01 jmcneill Exp $ */ +/* $NetBSD: drm_vm.c,v 1.11 2008/06/20 00:14:28 bjs Exp $ */ /*- * Copyright 2003 Eric Anholt @@ -24,7 +24,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: drm_vm.c,v 1.10 2008/05/04 21:43:01 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: drm_vm.c,v 1.11 2008/06/20 00:14:28 bjs Exp $"); /* __FBSDID("$FreeBSD: src/sys/dev/drm/drm_vm.c,v 1.2 2005/11/28 23:13:53 anholt Exp $"); */ @@ -86,13 +86,20 @@ paddr_t drm_mmap(dev_t kdev, off_t offset, int prot) roffset = DRM_NETBSD_HANDLE2ADDR(offset); TAILQ_FOREACH(map, &dev->maplist, link) { if (map->type == _DRM_SHM) { - if (roffset >= (uintptr_t)map->handle && roffset < (uintptr_t)map->handle + map->size) + if ((roffset >= (uintptr_t)map->handle) && + (roffset < (uintptr_t)map->handle + map->size)) { + DRM_DEBUG("found _DRM_SHM map for offset (%lx)\n", roffset); break; + } } else { - if (offset >= map->offset && offset < map->offset + map->size) + if ((offset >= map->cookie) && + (offset < map->cookie + map->size)) { + DRM_DEBUG("found cookie (%lx) for offset (%lx)", map->cookie, offset); + offset -= map->cookie; break; } } + } if (map == NULL) { DRM_UNLOCK(); @@ -111,16 +118,22 @@ paddr_t drm_mmap(dev_t kdev, off_t offset, int prot) case _DRM_FRAME_BUFFER: case _DRM_REGISTERS: case _DRM_AGP: - phys = offset; + phys = offset + map->offset; break; + /* All _DRM_CONSISTENT and _DRM_SHM mappings have a 0 offset */ case _DRM_CONSISTENT: - phys = vtophys((paddr_t)map->handle + (offset - map->offset)); + return bus_dmamem_mmap(dev->pa.pa_dmat, map->dmah->mem->dd_segs, + map->dmah->mem->dd_nsegs, 0, prot, BUS_DMA_NOWAIT| + BUS_DMA_NOCACHE); + case _DRM_SHM: + return bus_dmamem_mmap(dev->pa.pa_dmat, map->mem->dd_segs, + map->mem->dd_nsegs, 0, prot, BUS_DMA_NOWAIT); break; case _DRM_SCATTER_GATHER: - phys = vtophys(offset); - break; - case _DRM_SHM: - phys = vtophys(DRM_NETBSD_HANDLE2ADDR(offset)); + return bus_dmamem_mmap(dev->pa.pa_dmat, + dev->sg->mem->dd_segs, dev->sg->mem->dd_nsegs, + map->offset - dev->sg->handle + offset, prot, + BUS_DMA_NOWAIT|BUS_DMA_NOCACHE); break; default: DRM_ERROR("bad map type %d\n", type); @@ -133,4 +146,3 @@ paddr_t drm_mmap(dev_t kdev, off_t offset, int prot) return atop(phys); #endif } - diff --git a/sys/dev/drm/files.drm b/sys/dev/drm/files.drm index c1f0e0952be..341d01d6152 100644 --- a/sys/dev/drm/files.drm +++ b/sys/dev/drm/files.drm @@ -1,4 +1,4 @@ -# $NetBSD: files.drm,v 1.2 2007/03/28 11:29:37 jmcneill Exp $ +# $NetBSD: files.drm,v 1.3 2008/06/20 00:14:28 bjs Exp $ # direct rendering modules define drmbase @@ -15,6 +15,7 @@ file dev/drm/drm_ioctl.c drmbase file dev/drm/drm_irq.c drmbase file dev/drm/drm_lock.c drmbase file dev/drm/drm_memory.c drmbase +file dev/drm/drm_netbsd.c drmbase file dev/drm/drm_pci.c drmbase file dev/drm/drm_scatter.c drmbase file dev/drm/drm_sysctl.c drmbase |
