summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorbjs <bjs@NetBSD.org>2008-06-20 00:14:28 +0000
committerbjs <bjs@NetBSD.org>2008-06-20 00:14:28 +0000
commit6c1a2fee8fb51164b08f567435e20dc1bb290d26 (patch)
tree9cd75fc7f6d250aa1c96a35d4d62757a43a9efb1 /sys/dev
parent4537375adaf1705a195eccceffff47ec5dd39d85 (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.h54
-rw-r--r--sys/dev/drm/drm_auth.c6
-rw-r--r--sys/dev/drm/drm_bufs.c59
-rw-r--r--sys/dev/drm/drm_drv.c8
-rw-r--r--sys/dev/drm/drm_irq.c18
-rw-r--r--sys/dev/drm/drm_memory.c19
-rw-r--r--sys/dev/drm/drm_pci.c58
-rw-r--r--sys/dev/drm/drm_scatter.c45
-rw-r--r--sys/dev/drm/drm_vm.c34
-rw-r--r--sys/dev/drm/files.drm3
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