summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Anholt <anholt@freebsd.org>2005-04-26 05:19:11 +0000
committerEric Anholt <anholt@freebsd.org>2005-04-26 05:19:11 +0000
commitec111d70fee0647c4c68a02c723d4a3729c93b56 (patch)
tree114a3257310a979d3dea484af62322ba007bf1e0
parent31a06d0baca9e378a773ca8bd350860546dd8a79 (diff)
Convert BSD code to mostly use bus_dma, the dma abstraction for dealing
with IOMMUs and such. There is one usage of the forbidden vtophys() left in drm_scatter.c which will be fixed up soon. This required a KPI change for drm_pci_alloc/free() to return/use a drm_dma_handle_t that keeps track of os-specific bits, rather than just passing around the vaddr/busaddr/size. Submitted by: Tonnerre Lombard (partially) Tested on: FreeBSD: Rage128 AGP/PCI Linux: Savage4 AGP/PCI
-rw-r--r--bsd-core/ati_pcigart.c72
-rw-r--r--bsd-core/drmP.h24
-rw-r--r--bsd-core/drm_bufs.c45
-rw-r--r--bsd-core/drm_dma.c5
-rw-r--r--bsd-core/drm_pci.c93
-rw-r--r--bsd-core/drm_scatter.c15
-rw-r--r--linux-core/drmP.h14
-rw-r--r--linux-core/drm_bufs.c17
-rw-r--r--linux-core/drm_drv.c8
-rw-r--r--linux-core/drm_pci.c34
-rw-r--r--linux-core/drm_vm.c8
-rw-r--r--shared-core/i915_dma.c14
-rw-r--r--shared-core/i915_drv.h3
-rw-r--r--shared-core/mach64_dma.c39
-rw-r--r--shared-core/mach64_drv.h2
15 files changed, 233 insertions, 160 deletions
diff --git a/bsd-core/ati_pcigart.c b/bsd-core/ati_pcigart.c
index ae18a957..2eff5be1 100644
--- a/bsd-core/ati_pcigart.c
+++ b/bsd-core/ati_pcigart.c
@@ -31,53 +31,44 @@
#include "drmP.h"
-#if PAGE_SIZE == 8192
-# define ATI_PCIGART_TABLE_ORDER 2
-# define ATI_PCIGART_TABLE_PAGES (1 << 2)
-#elif PAGE_SIZE == 4096
-# define ATI_PCIGART_TABLE_ORDER 3
-# define ATI_PCIGART_TABLE_PAGES (1 << 3)
-#elif
-# error - PAGE_SIZE not 8K or 4K
-#endif
-
-# define ATI_MAX_PCIGART_PAGES 8192 /* 32 MB aperture, 4K pages */
-# define ATI_PCIGART_PAGE_SIZE 4096 /* PCI GART page size */
+#define ATI_PCIGART_PAGE_SIZE 4096 /* PCI GART page size */
+#define ATI_MAX_PCIGART_PAGES 8192 /* 32 MB aperture, 4K pages */
+#define ATI_PCIGART_TABLE_SIZE 32768
int drm_ati_pcigart_init(drm_device_t *dev, unsigned long *addr,
dma_addr_t *bus_addr)
{
- drm_sg_mem_t *entry = dev->sg;
- unsigned long address = 0;
unsigned long pages;
- u32 *pci_gart=0, page_base, bus_address = 0;
- int i, j, ret = 0;
+ u32 *pci_gart = 0, page_base;
+ int i, j;
- if ( !entry ) {
+ *addr = 0;
+ *bus_addr = 0;
+
+ if (dev->sg == NULL) {
DRM_ERROR( "no scatter/gather memory!\n" );
- goto done;
+ return 0;
}
- address = (long)contigmalloc((1 << ATI_PCIGART_TABLE_ORDER) * PAGE_SIZE,
- M_DRM, M_NOWAIT, 0ul, 0xfffffffful, PAGE_SIZE, 0);
- if ( !address ) {
- DRM_ERROR( "cannot allocate PCI GART page!\n" );
- goto done;
+ dev->sg->dmah = drm_pci_alloc(dev, ATI_PCIGART_TABLE_SIZE, 0,
+ 0xfffffffful);
+ if (dev->sg->dmah == NULL) {
+ DRM_ERROR("cannot allocate PCI GART table!\n");
+ return 0;
}
- /* XXX: we need to busdma this */
- bus_address = vtophys( address );
+ *addr = (long)dev->sg->dmah->vaddr;
+ *bus_addr = dev->sg->dmah->busaddr;
+ pci_gart = (u32 *)dev->sg->dmah->vaddr;
- pci_gart = (u32 *)address;
+ pages = DRM_MIN(dev->sg->pages, ATI_MAX_PCIGART_PAGES);
- pages = ( entry->pages <= ATI_MAX_PCIGART_PAGES )
- ? entry->pages : ATI_MAX_PCIGART_PAGES;
+ bzero(pci_gart, ATI_PCIGART_TABLE_SIZE);
- bzero( pci_gart, ATI_MAX_PCIGART_PAGES * sizeof(u32) );
+ KASSERT(PAGE_SIZE >= ATI_PCIGART_PAGE_SIZE, "page size too small");
for ( i = 0 ; i < pages ; i++ ) {
- entry->busaddr[i] = vtophys( entry->handle + (i*PAGE_SIZE) );
- page_base = (u32) entry->busaddr[i];
+ page_base = (u32) dev->sg->busaddr[i];
for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) {
*pci_gart++ = cpu_to_le32( page_base );
@@ -87,29 +78,18 @@ int drm_ati_pcigart_init(drm_device_t *dev, unsigned long *addr,
DRM_MEMORYBARRIER();
- ret = 1;
-
-done:
- *addr = address;
- *bus_addr = bus_address;
- return ret;
+ return 1;
}
int drm_ati_pcigart_cleanup(drm_device_t *dev, unsigned long addr,
dma_addr_t bus_addr)
{
- drm_sg_mem_t *entry = dev->sg;
-
- /* we need to support large memory configurations */
- if ( !entry ) {
+ if (dev->sg == NULL) {
DRM_ERROR( "no scatter/gather memory!\n" );
return 0;
}
-#if __FreeBSD_version > 500000
- /* Not available on 4.x */
- contigfree((void *)addr, (1 << ATI_PCIGART_TABLE_ORDER) * PAGE_SIZE,
- M_DRM);
-#endif
+ drm_pci_free(dev, dev->sg->dmah);
+
return 1;
}
diff --git a/bsd-core/drmP.h b/bsd-core/drmP.h
index ca28ea2c..6af29718 100644
--- a/bsd-core/drmP.h
+++ b/bsd-core/drmP.h
@@ -481,14 +481,24 @@ typedef struct drm_freelist {
int high_mark; /* High water mark */
} drm_freelist_t;
+typedef struct drm_dma_handle {
+ void *vaddr;
+ bus_addr_t busaddr;
+#if defined(__FreeBSD__)
+ bus_dma_tag_t tag;
+ bus_dmamap_t map;
+#elif defined(__NetBSD__)
+ bus_dma_segment_t seg;
+#endif
+} drm_dma_handle_t;
+
typedef struct drm_buf_entry {
int buf_size;
int buf_count;
drm_buf_t *buflist;
int seg_count;
+ drm_dma_handle_t **seglist;
int page_order;
- vm_offset_t *seglist;
- dma_addr_t *seglist_bus;
drm_freelist_t freelist;
} drm_buf_entry_t;
@@ -558,9 +568,9 @@ typedef struct drm_agp_head {
typedef struct drm_sg_mem {
unsigned long handle;
- void *virtual;
int pages;
dma_addr_t *busaddr;
+ drm_dma_handle_t *dmah; /* Handle to PCI memory for ATI PCIGART table */
} drm_sg_mem_t;
typedef TAILQ_HEAD(drm_map_list, drm_local_map) drm_map_list_t;
@@ -579,6 +589,7 @@ typedef struct drm_local_map {
struct resource *bsr;
bus_space_tag_t bst;
bus_space_handle_t bsh;
+ drm_dma_handle_t *dmah;
TAILQ_ENTRY(drm_local_map) link;
} drm_local_map_t;
@@ -910,10 +921,9 @@ int drm_sg_alloc(DRM_IOCTL_ARGS);
int drm_sg_free(DRM_IOCTL_ARGS);
/* consistent PCI memory functions (drm_pci.c) */
-void *drm_pci_alloc(drm_device_t *dev, size_t size, size_t align,
- dma_addr_t maxaddr, dma_addr_t *busaddr);
-void drm_pci_free(drm_device_t *dev, size_t size, void *vaddr,
- dma_addr_t busaddr);
+drm_dma_handle_t *drm_pci_alloc(drm_device_t *dev, size_t size, size_t align,
+ dma_addr_t maxaddr);
+void drm_pci_free(drm_device_t *dev, drm_dma_handle_t *dmah);
/* Inline replacements for DRM_IOREMAP macros */
static __inline__ void drm_core_ioremap(struct drm_local_map *map, struct drm_device *dev)
diff --git a/bsd-core/drm_bufs.c b/bsd-core/drm_bufs.c
index 0461ebeb..0f1b7a03 100644
--- a/bsd-core/drm_bufs.c
+++ b/bsd-core/drm_bufs.c
@@ -151,7 +151,6 @@ int drm_addmap(DRM_IOCTL_ARGS)
DRM_DEVICE;
drm_map_t request;
drm_local_map_t *map;
- dma_addr_t bus_addr;
if (!(dev->flags & (FREAD|FWRITE)))
return DRM_ERR(EACCES); /* Require read/write */
@@ -246,13 +245,14 @@ int drm_addmap(DRM_IOCTL_ARGS)
map->offset = map->offset + dev->sg->handle;
break;
case _DRM_CONSISTENT:
- map->handle = drm_pci_alloc(dev, map->size, map->size,
- 0xfffffffful, &bus_addr);
- if (map->handle == NULL) {
+ map->dmah = drm_pci_alloc(dev, map->size, map->size,
+ 0xfffffffful);
+ if (map->dmah == NULL) {
free(map, M_DRM);
return ENOMEM;
}
- map->offset = (unsigned long)bus_addr;
+ map->handle = map->dmah->vaddr;
+ map->offset = map->dmah->busaddr;
break;
default:
free(map, M_DRM);
@@ -310,7 +310,7 @@ void drm_remove_map(drm_device_t *dev, drm_local_map_t *map)
case _DRM_SCATTER_GATHER:
break;
case _DRM_CONSISTENT:
- drm_pci_free(dev, map->size, map->handle, map->offset);
+ drm_pci_free(dev, map->dmah);
break;
}
@@ -361,12 +361,9 @@ static void drm_cleanup_buf_error(drm_device_t *dev, drm_buf_entry_t *entry)
if (entry->seg_count) {
for (i = 0; i < entry->seg_count; i++) {
- drm_pci_free(dev, entry->buf_size,
- (void *)entry->seglist[i],
- entry->seglist_bus[i]);
+ drm_pci_free(dev, entry->seglist[i]);
}
free(entry->seglist, M_DRM);
- free(entry->seglist_bus, M_DRM);
entry->seg_count = 0;
}
@@ -499,7 +496,6 @@ static int drm_addbufs_pci(drm_device_t *dev, drm_buf_desc_t *request)
int total;
int page_order;
drm_buf_entry_t *entry;
- vm_offset_t vaddr;
drm_buf_t *buf;
int alignment;
unsigned long offset;
@@ -508,7 +504,6 @@ static int drm_addbufs_pci(drm_device_t *dev, drm_buf_desc_t *request)
int page_count;
unsigned long *temp_pagelist;
drm_buf_t **temp_buflist;
- dma_addr_t bus_addr;
count = request->count;
order = drm_order(request->size);
@@ -528,8 +523,6 @@ static int drm_addbufs_pci(drm_device_t *dev, drm_buf_desc_t *request)
M_NOWAIT | M_ZERO);
entry->seglist = malloc(count * sizeof(*entry->seglist), M_DRM,
M_NOWAIT | M_ZERO);
- entry->seglist_bus = malloc(count * sizeof(*entry->seglist_bus), M_DRM,
- M_NOWAIT | M_ZERO);
/* Keep the original pagelist until we know all the allocations
* have succeeded
@@ -538,10 +531,9 @@ static int drm_addbufs_pci(drm_device_t *dev, drm_buf_desc_t *request)
sizeof(*dma->pagelist), M_DRM, M_NOWAIT);
if (entry->buflist == NULL || entry->seglist == NULL ||
- entry->seglist_bus == NULL || temp_pagelist == NULL) {
+ temp_pagelist == NULL) {
free(entry->buflist, M_DRM);
free(entry->seglist, M_DRM);
- free(entry->seglist_bus, M_DRM);
return DRM_ERR(ENOMEM);
}
@@ -557,9 +549,9 @@ static int drm_addbufs_pci(drm_device_t *dev, drm_buf_desc_t *request)
page_count = 0;
while ( entry->buf_count < count ) {
- vaddr = (vm_offset_t)drm_pci_alloc(dev, size, alignment,
- 0xfffffffful, &bus_addr);
- if (vaddr == 0) {
+ drm_dma_handle_t *dmah = drm_pci_alloc(dev, size, alignment,
+ 0xfffffffful);
+ if (dmah == NULL) {
/* Set count correctly so we free the proper amount. */
entry->buf_count = count;
entry->seg_count = count;
@@ -567,15 +559,14 @@ static int drm_addbufs_pci(drm_device_t *dev, drm_buf_desc_t *request)
free(temp_pagelist, M_DRM);
return DRM_ERR(ENOMEM);
}
-
- entry->seglist_bus[entry->seg_count] = bus_addr;
- entry->seglist[entry->seg_count++] = vaddr;
+
+ entry->seglist[entry->seg_count++] = dmah;
for ( i = 0 ; i < (1 << page_order) ; i++ ) {
- DRM_DEBUG( "page %d @ 0x%08lx\n",
+ DRM_DEBUG( "page %d @ %p\n",
dma->page_count + page_count,
- (long)vaddr + PAGE_SIZE * i );
+ (char *)dmah->vaddr + PAGE_SIZE * i );
temp_pagelist[dma->page_count + page_count++] =
- vaddr + PAGE_SIZE * i;
+ (long)dmah->vaddr + PAGE_SIZE * i;
}
for ( offset = 0 ;
offset + size <= total && entry->buf_count < count ;
@@ -586,8 +577,8 @@ static int drm_addbufs_pci(drm_device_t *dev, drm_buf_desc_t *request)
buf->order = order;
buf->used = 0;
buf->offset = (dma->byte_count + byte_count + offset);
- buf->address = (void *)(vaddr + offset);
- buf->bus_address = bus_addr + offset;
+ buf->address = ((char *)dmah->vaddr + offset);
+ buf->bus_address = dmah->busaddr + offset;
buf->next = NULL;
buf->pending = 0;
buf->filp = NULL;
diff --git a/bsd-core/drm_dma.c b/bsd-core/drm_dma.c
index adc352b6..6377d71e 100644
--- a/bsd-core/drm_dma.c
+++ b/bsd-core/drm_dma.c
@@ -62,12 +62,9 @@ void drm_dma_takedown(drm_device_t *dev)
dma->bufs[i].buf_count,
dma->bufs[i].seg_count);
for (j = 0; j < dma->bufs[i].seg_count; j++) {
- drm_pci_free(dev, dma->bufs[i].buf_size,
- (void *)dma->bufs[i].seglist[j],
- dma->bufs[i].seglist_bus[j]);
+ drm_pci_free(dev, dma->bufs[i].seglist[j]);
}
free(dma->bufs[i].seglist, M_DRM);
- free(dma->bufs[i].seglist_bus, M_DRM);
}
if (dma->bufs[i].buf_count) {
diff --git a/bsd-core/drm_pci.c b/bsd-core/drm_pci.c
index 29ed4790..0f431dd6 100644
--- a/bsd-core/drm_pci.c
+++ b/bsd-core/drm_pci.c
@@ -34,34 +34,101 @@
/** \name PCI memory */
/*@{*/
+#if defined(__FreeBSD__)
+static void
+drm_pci_busdma_callback(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
+{
+ drm_dma_handle_t *dmah = arg;
+
+ if (error != 0)
+ return;
+
+ KASSERT(nsegs == 1, ("drm_pci_busdma_callback: bad dma segment count"));
+ dmah->busaddr = segs[0].ds_addr;
+}
+#endif
+
/**
* \brief Allocate a physically contiguous DMA-accessible consistent
* memory block.
*/
-void *
-drm_pci_alloc(drm_device_t *dev, size_t size, size_t align, dma_addr_t maxaddr,
- dma_addr_t *busaddr)
+drm_dma_handle_t *
+drm_pci_alloc(drm_device_t *dev, size_t size, size_t align, dma_addr_t maxaddr)
{
- void *vaddr;
+ drm_dma_handle_t *dmah;
+ int ret;
+
+ dmah = malloc(sizeof(drm_dma_handle_t), M_DRM, M_ZERO | M_NOWAIT);
+ if (dmah == NULL)
+ return NULL;
- vaddr = contigmalloc(size, M_DRM, M_NOWAIT, 0ul, maxaddr, align,
- 0);
- *busaddr = vtophys(vaddr);
-
- return vaddr;
+#ifdef __FreeBSD__
+ ret = bus_dma_tag_create(NULL, align, 0, /* tag, align, boundary */
+ maxaddr, BUS_SPACE_MAXADDR, /* lowaddr, highaddr */
+ NULL, NULL, /* filtfunc, filtfuncargs */
+ size, 1, size, /* maxsize, nsegs, maxsegsize */
+ BUS_DMA_ALLOCNOW, NULL, NULL, /* flags, lockfunc, lockfuncargs */
+ &dmah->tag);
+ if (ret != 0) {
+ free(dmah, M_DRM);
+ return NULL;
+ }
+
+ ret = bus_dmamem_alloc(dmah->tag, &dmah->vaddr, BUS_DMA_NOWAIT,
+ &dmah->map);
+ if (ret != 0) {
+ bus_dma_tag_destroy(dmah->tag);
+ free(dmah, M_DRM);
+ return NULL;
+ }
+
+ ret = bus_dmamap_load(dmah->tag, dmah->map, dmah->vaddr, size,
+ drm_pci_busdma_callback, dmah, 0);
+ if (ret != 0) {
+ bus_dmamem_free(dmah->tag, dmah->vaddr, dmah->map);
+ bus_dma_tag_destroy(dmah->tag);
+ free(dmah, M_DRM);
+ return NULL;
+ }
+#elif defined(__NetBSD__)
+ ret = bus_dmamem_alloc(dev->dma_tag, size, align, PAGE_SIZE,
+ &dmah->seg, 1, &nsegs, BUS_DMA_NOWAIT);
+ if ((ret != 0) || (nsegs != 1)) {
+ free(dmah, M_DRM);
+ return NULL;
+ }
+
+ ret = bus_dmamem_map(dev->dma_tag, &dmah->seg, 1, size, &dmah->addr,
+ BUS_DMA_NOWAIT);
+ if (ret != 0) {
+ bus_dmamem_free(dev->dma_tag, &dmah->seg, 1);
+ free(dmah, M_DRM);
+ return NULL;
+ }
+
+ dmah->dmaaddr = h->seg.ds_addr;
+#endif
+
+ return dmah;
}
/**
* \brief Free a DMA-accessible consistent memory block.
*/
void
-drm_pci_free(drm_device_t *dev, size_t size, void *vaddr, dma_addr_t busaddr)
+drm_pci_free(drm_device_t *dev, drm_dma_handle_t *dmah)
{
-#if __FreeBSD_version > 500000
- if (vaddr == NULL)
+ if (dmah == NULL)
return;
- contigfree(vaddr, size, M_DRM); /* Not available on 4.x */
+
+#if defined(__FreeBSD__)
+ bus_dmamem_free(dmah->tag, dmah->vaddr, dmah->map);
+ bus_dma_tag_destroy(dmah->tag);
+#elif defined(__NetBSD__)
+ bus_dmamem_free(dev->dma_tag, &dmah->seg, 1);
#endif
+
+ free(dmah, M_DRM);
}
/*@}*/
diff --git a/bsd-core/drm_scatter.c b/bsd-core/drm_scatter.c
index 107905af..c26a3802 100644
--- a/bsd-core/drm_scatter.c
+++ b/bsd-core/drm_scatter.c
@@ -35,7 +35,7 @@
void drm_sg_cleanup(drm_sg_mem_t *entry)
{
- free(entry->virtual, M_DRM);
+ free((void *)entry->handle, M_DRM);
free(entry->busaddr, M_DRM);
free(entry, M_DRM);
}
@@ -46,6 +46,7 @@ int drm_sg_alloc(DRM_IOCTL_ARGS)
drm_scatter_gather_t request;
drm_sg_mem_t *entry;
unsigned long pages;
+ int i;
DRM_DEBUG( "%s\n", __FUNCTION__ );
@@ -71,16 +72,18 @@ int drm_sg_alloc(DRM_IOCTL_ARGS)
return ENOMEM;
}
- entry->virtual = malloc(pages << PAGE_SHIFT, M_DRM, M_WAITOK | M_ZERO);
- if ( !entry->virtual ) {
+ entry->handle = (long)malloc(pages << PAGE_SHIFT, M_DRM,
+ M_WAITOK | M_ZERO);
+ if (entry->handle == 0) {
drm_sg_cleanup(entry);
return ENOMEM;
}
- entry->handle = (unsigned long)entry->virtual;
+ for (i = 0; i < pages; i++) {
+ entry->busaddr[i] = vtophys(entry->handle + i * PAGE_SIZE);
+ }
DRM_DEBUG( "sg alloc handle = %08lx\n", entry->handle );
- DRM_DEBUG( "sg alloc virtual = %p\n", entry->virtual );
request.handle = entry->handle;
@@ -117,7 +120,7 @@ int drm_sg_free(DRM_IOCTL_ARGS)
if ( !entry || entry->handle != request.handle )
return EINVAL;
- DRM_DEBUG( "sg free virtual = %p\n", entry->virtual );
+ DRM_DEBUG( "sg free virtual = 0x%lx\n", entry->handle );
drm_sg_cleanup(entry);
diff --git a/linux-core/drmP.h b/linux-core/drmP.h
index cdf7e76f..b7f4640f 100644
--- a/linux-core/drmP.h
+++ b/linux-core/drmP.h
@@ -482,6 +482,12 @@ typedef struct drm_sigdata {
drm_hw_lock_t *lock;
} drm_sigdata_t;
+typedef struct drm_dma_handle {
+ dma_addr_t busaddr;
+ void *vaddr;
+ size_t size;
+} drm_dma_handle_t;
+
/**
* Mappings list
*/
@@ -959,11 +965,9 @@ extern int drm_ati_pcigart_init(drm_device_t * dev,
extern int drm_ati_pcigart_cleanup(drm_device_t * dev,
unsigned long addr, dma_addr_t bus_addr);
-extern void *drm_pci_alloc(drm_device_t * dev, size_t size,
- size_t align, dma_addr_t maxaddr,
- dma_addr_t * busaddr);
-extern void drm_pci_free(drm_device_t * dev, size_t size,
- void *vaddr, dma_addr_t busaddr);
+extern drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size,
+ size_t align, dma_addr_t maxaddr);
+extern void drm_pci_free(drm_device_t * dev, drm_dma_handle_t *dmah);
/* sysfs support (drm_sysfs.c) */
struct drm_sysfs_class;
diff --git a/linux-core/drm_bufs.c b/linux-core/drm_bufs.c
index 6339ac21..5f1336ff 100644
--- a/linux-core/drm_bufs.c
+++ b/linux-core/drm_bufs.c
@@ -130,6 +130,7 @@ int drm_addmap(struct inode *inode, struct file *filp,
drm_map_t *map;
drm_map_t __user *argp = (void __user *)arg;
drm_map_list_t *list;
+ drm_dma_handle_t *dmah;
if (!(filp->f_mode & 3))
return -EACCES; /* Require read/write */
@@ -261,14 +262,13 @@ int drm_addmap(struct inode *inode, struct file *filp,
* As we're limiting the address to 2^32-1 (or less),
* casting it down to 32 bits is no problem, but we
* need to point to a 64bit variable first. */
- dma_addr_t bus_addr;
- map->handle = drm_pci_alloc(dev, map->size, map->size,
- 0xffffffffUL, &bus_addr);
- map->offset = (unsigned long)bus_addr;
- if (!map->handle) {
+ dmah = drm_pci_alloc(dev, map->size, map->size, 0xffffffffUL);
+ if (!dmah) {
drm_free(map, sizeof(*map), DRM_MEM_MAPS);
return -ENOMEM;
}
+ map->handle = dmah->vaddr;
+ map->offset = (unsigned long)dmah->busaddr;
break;
}
default:
@@ -364,6 +364,8 @@ int drm_rmmap(struct inode *inode, struct file *filp,
}
if (!found_maps) {
+ drm_dma_handle_t dmah;
+
switch (map->type) {
case _DRM_REGISTERS:
case _DRM_FRAME_BUFFER:
@@ -375,7 +377,10 @@ int drm_rmmap(struct inode *inode, struct file *filp,
case _DRM_SCATTER_GATHER:
break;
case _DRM_CONSISTENT:
- drm_pci_free(dev, map->size, map->handle, map->offset);
+ dmah.vaddr = map->handle;
+ dmah.busaddr = map->offset;
+ dmah.size = map->size;
+ drm_pci_free(dev, &dmah);
break;
}
drm_free(map, sizeof(*map), DRM_MEM_MAPS);
diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c
index 42ca3c3b..069ecd3e 100644
--- a/linux-core/drm_drv.c
+++ b/linux-core/drm_drv.c
@@ -207,6 +207,8 @@ int drm_takedown(drm_device_t * dev)
r_list = (drm_map_list_t *) list;
if ((map = r_list->map)) {
+ drm_dma_handle_t dmah;
+
switch (map->type) {
case _DRM_REGISTERS:
case _DRM_FRAME_BUFFER:
@@ -230,8 +232,10 @@ int drm_takedown(drm_device_t * dev)
}
break;
case _DRM_CONSISTENT:
- drm_pci_free(dev, map->size,
- map->handle, map->offset);
+ dmah.vaddr = map->handle;
+ dmah.busaddr = map->offset;
+ dmah.size = map->size;
+ drm_pci_free(dev, &dmah);
break;
}
drm_free(map, sizeof(*map), DRM_MEM_MAPS);
diff --git a/linux-core/drm_pci.c b/linux-core/drm_pci.c
index 30e1ba8d..f8f221cd 100644
--- a/linux-core/drm_pci.c
+++ b/linux-core/drm_pci.c
@@ -46,10 +46,10 @@
/**
* \brief Allocate a PCI consistent memory block, for DMA.
*/
-void *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align,
- dma_addr_t maxaddr, dma_addr_t * busaddr)
+drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align,
+ dma_addr_t maxaddr)
{
- void *address;
+ drm_dma_handle_t *dmah;
#if 0
unsigned long addr;
size_t sz;
@@ -78,13 +78,18 @@ void *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align,
return NULL;
}
- address = pci_alloc_consistent(dev->pdev, size, busaddr);
+ dmah = kmalloc(sizeof(drm_dma_handle_t), GFP_KERNEL);
+ if (!dmah)
+ return NULL;
+
+ dmah->vaddr = pci_alloc_consistent(dev->pdev, size, &dmah->busaddr);
#if DRM_DEBUG_MEMORY
- if (address == NULL) {
+ if (dmah->vaddr == NULL) {
spin_lock(&drm_mem_lock);
++drm_mem_stats[area].fail_count;
spin_unlock(&drm_mem_lock);
+ kfree(dmah);
return NULL;
}
@@ -94,22 +99,24 @@ void *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align,
drm_ram_used += size;
spin_unlock(&drm_mem_lock);
#else
- if (address == NULL)
+ if (dmah->vaddr == NULL) {
+ kfree(dmah);
return NULL;
+ }
#endif
- memset(address, 0, size);
+ memset(dmah->vaddr, 0, size);
#if 0
/* XXX - Is virt_to_page() legal for consistent mem? */
/* Reserve */
- for (addr = (unsigned long)address, sz = size;
+ for (addr = (unsigned long)dmah->vaddr, sz = size;
sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) {
SetPageReserved(virt_to_page(addr));
}
#endif
- return address;
+ return dmah;
}
EXPORT_SYMBOL(drm_pci_alloc);
@@ -117,7 +124,7 @@ EXPORT_SYMBOL(drm_pci_alloc);
* \brief Free a PCI consistent memory block.
*/
void
-drm_pci_free(drm_device_t * dev, size_t size, void *vaddr, dma_addr_t busaddr)
+drm_pci_free(drm_device_t * dev, drm_dma_handle_t *dmah)
{
#if 0
unsigned long addr;
@@ -129,7 +136,7 @@ drm_pci_free(drm_device_t * dev, size_t size, void *vaddr, dma_addr_t busaddr)
int free_count;
#endif
- if (!vaddr) {
+ if (!dmah->vaddr) {
#if DRM_DEBUG_MEMORY
DRM_MEM_ERROR(area, "Attempt to free address 0\n");
#endif
@@ -137,12 +144,13 @@ drm_pci_free(drm_device_t * dev, size_t size, void *vaddr, dma_addr_t busaddr)
#if 0
/* XXX - Is virt_to_page() legal for consistent mem? */
/* Unreserve */
- for (addr = (unsigned long)vaddr, sz = size;
+ for (addr = (unsigned long)dmah->vaddr, sz = size;
sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) {
ClearPageReserved(virt_to_page(addr));
}
#endif
- pci_free_consistent(dev->pdev, size, vaddr, busaddr);
+ pci_free_consistent(dev->pdev, dmah->size, dmah->vaddr,
+ dmah->busaddr);
}
#if DRM_DEBUG_MEMORY
diff --git a/linux-core/drm_vm.c b/linux-core/drm_vm.c
index 02520c76..bb982b80 100644
--- a/linux-core/drm_vm.c
+++ b/linux-core/drm_vm.c
@@ -218,6 +218,8 @@ void drm_vm_shm_close(struct vm_area_struct *vma)
}
if (!found_maps) {
+ drm_dma_handle_t dmah;
+
switch (map->type) {
case _DRM_REGISTERS:
case _DRM_FRAME_BUFFER:
@@ -237,8 +239,10 @@ void drm_vm_shm_close(struct vm_area_struct *vma)
case _DRM_SCATTER_GATHER:
break;
case _DRM_CONSISTENT:
- drm_pci_free(dev, map->size, map->handle,
- map->offset);
+ dmah.vaddr = map->handle;
+ dmah.busaddr = map->offset;
+ dmah.size = map->size;
+ drm_pci_free(dev, &dmah);
break;
}
drm_free(map, sizeof(*map), DRM_MEM_MAPS);
diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c
index ac96f37d..9c27706b 100644
--- a/shared-core/i915_dma.c
+++ b/shared-core/i915_dma.c
@@ -75,9 +75,8 @@ static int i915_dma_cleanup(drm_device_t * dev)
drm_core_ioremapfree(&dev_priv->ring.map, dev);
}
- if (dev_priv->hw_status_page) {
- drm_pci_free(dev, PAGE_SIZE, dev_priv->hw_status_page,
- dev_priv->dma_status_page);
+ if (dev_priv->status_page_dmah) {
+ drm_pci_free(dev, dev_priv->status_page_dmah);
/* Need to rewrite hardware status page */
I915_WRITE(0x02080, 0x1ffff000);
}
@@ -154,15 +153,18 @@ static int i915_initialize(drm_device_t * dev,
dev_priv->allow_batchbuffer = 1;
/* Program Hardware Status Page */
- dev_priv->hw_status_page = drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE,
- 0xffffffff, &dev_priv->dma_status_page);
+ dev_priv->status_page_dmah = drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE,
+ 0xffffffff);
- if (!dev_priv->hw_status_page) {
+ if (!dev_priv->status_page_dmah) {
dev->dev_private = (void *)dev_priv;
i915_dma_cleanup(dev);
DRM_ERROR("Can not allocate hardware status page\n");
return DRM_ERR(ENOMEM);
}
+ dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr;
+ dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
+
memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h
index a4294159..b9615341 100644
--- a/shared-core/i915_drv.h
+++ b/shared-core/i915_drv.h
@@ -55,9 +55,10 @@ typedef struct drm_i915_private {
drm_i915_sarea_t *sarea_priv;
drm_i915_ring_buffer_t ring;
+ drm_dma_handle_t *status_page_dmah;
void *hw_status_page;
- unsigned long counter;
dma_addr_t dma_status_page;
+ unsigned long counter;
int back_offset;
int front_offset;
diff --git a/shared-core/mach64_dma.c b/shared-core/mach64_dma.c
index b32dde2b..d7e97a99 100644
--- a/shared-core/mach64_dma.c
+++ b/shared-core/mach64_dma.c
@@ -575,8 +575,7 @@ void mach64_dump_ring_info(drm_mach64_private_t * dev_priv)
static int mach64_bm_dma_test(drm_device_t * dev)
{
drm_mach64_private_t *dev_priv = dev->dev_private;
- dma_addr_t data_handle;
- void *cpu_addr_data;
+ drm_dma_handle_t *cpu_addr_dmah;
u32 data_addr;
u32 *table, *data;
u32 expected[2];
@@ -589,14 +588,14 @@ static int mach64_bm_dma_test(drm_device_t * dev)
/* FIXME: get a dma buffer from the freelist here */
DRM_DEBUG("Allocating data memory ...\n");
- cpu_addr_data =
- drm_pci_alloc(dev, 0x1000, 0x1000, 0xfffffffful, &data_handle);
- if (!cpu_addr_data || !data_handle) {
+ cpu_addr_dmah =
+ drm_pci_alloc(dev, 0x1000, 0x1000, 0xfffffffful);
+ if (!cpu_addr_dmah) {
DRM_INFO("data-memory allocation failed!\n");
return DRM_ERR(ENOMEM);
} else {
- data = (u32 *) cpu_addr_data;
- data_addr = (u32) data_handle;
+ data = (u32 *) cpu_addr_dmah->vaddr;
+ data_addr = (u32) cpu_addr_dmah->busaddr;
}
/* Save the X server's value for SRC_CNTL and restore it
@@ -624,7 +623,7 @@ static int mach64_bm_dma_test(drm_device_t * dev)
DRM_INFO("resetting engine ...\n");
mach64_do_engine_reset(dev_priv);
DRM_INFO("freeing data buffer memory.\n");
- drm_pci_free(dev, 0x1000, cpu_addr_data, data_handle);
+ drm_pci_free(dev, cpu_addr_dmah);
return DRM_ERR(EIO);
}
}
@@ -679,7 +678,7 @@ static int mach64_bm_dma_test(drm_device_t * dev)
MACH64_WRITE(MACH64_PAT_REG0, pat_reg0);
MACH64_WRITE(MACH64_PAT_REG1, pat_reg1);
DRM_INFO("freeing data buffer memory.\n");
- drm_pci_free(dev, 0x1000, cpu_addr_data, data_handle);
+ drm_pci_free(dev, cpu_addr_dmah);
return i;
}
DRM_DEBUG("waiting for idle...done\n");
@@ -715,7 +714,7 @@ static int mach64_bm_dma_test(drm_device_t * dev)
MACH64_WRITE(MACH64_PAT_REG0, pat_reg0);
MACH64_WRITE(MACH64_PAT_REG1, pat_reg1);
DRM_INFO("freeing data buffer memory.\n");
- drm_pci_free(dev, 0x1000, cpu_addr_data, data_handle);
+ drm_pci_free(dev, cpu_addr_dmah);
return i;
}
@@ -743,7 +742,7 @@ static int mach64_bm_dma_test(drm_device_t * dev)
MACH64_WRITE(MACH64_PAT_REG1, pat_reg1);
DRM_DEBUG("freeing data buffer memory.\n");
- drm_pci_free(dev, 0x1000, cpu_addr_data, data_handle);
+ drm_pci_free(dev, cpu_addr_dmah);
DRM_DEBUG("returning ...\n");
return failed;
@@ -896,16 +895,17 @@ static int mach64_do_dma_init(drm_device_t * dev, drm_mach64_init_t * init)
dev_priv->ring.size = 0x4000; /* 16KB */
if (dev_priv->is_pci) {
- dev_priv->ring.start = drm_pci_alloc(dev, dev_priv->ring.size,
+ dev_priv->ring.dmah = drm_pci_alloc(dev, dev_priv->ring.size,
dev_priv->ring.size,
- 0xfffffffful,
- &dev_priv->ring.handle);
+ 0xfffffffful);
- if (!dev_priv->ring.start || !dev_priv->ring.handle) {
+ if (!dev_priv->ring.dmah) {
DRM_ERROR("Allocating dma descriptor ring failed\n");
return DRM_ERR(ENOMEM);
} else {
- dev_priv->ring.start_addr = (u32) dev_priv->ring.handle;
+ dev_priv->ring.start = dev_priv->ring.dmah->vaddr;
+ dev_priv->ring.start_addr =
+ (u32) dev_priv->ring.dmah->busaddr;
}
} else {
dev_priv->ring.start = dev_priv->ring_map->handle;
@@ -1149,11 +1149,8 @@ int mach64_do_cleanup_dma(drm_device_t * dev)
drm_mach64_private_t *dev_priv = dev->dev_private;
if (dev_priv->is_pci) {
- if ((dev_priv->ring.start != NULL)
- && dev_priv->ring.handle) {
- drm_pci_free(dev, dev_priv->ring.size,
- dev_priv->ring.start,
- dev_priv->ring.handle);
+ if (dev_priv->ring.dmah) {
+ drm_pci_free(dev, dev_priv->ring.dmah);
}
} else {
if (dev_priv->ring_map)
diff --git a/shared-core/mach64_drv.h b/shared-core/mach64_drv.h
index 698a6a51..fb3deb2f 100644
--- a/shared-core/mach64_drv.h
+++ b/shared-core/mach64_drv.h
@@ -60,7 +60,7 @@ typedef struct drm_mach64_freelist {
} drm_mach64_freelist_t;
typedef struct drm_mach64_descriptor_ring {
- dma_addr_t handle; /* handle (bus address) of ring returned by pci_alloc_consistent() */
+ drm_dma_handle_t *dmah; /* Handle to pci dma memory */
void *start; /* write pointer (cpu address) to start of descriptor ring */
u32 start_addr; /* bus address of beginning of descriptor ring */
int size; /* size of ring in bytes */