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
This commit is contained in:
Eric Anholt 2005-04-26 05:19:11 +00:00
parent 31a06d0bac
commit ec111d70fe
15 changed files with 233 additions and 160 deletions

View file

@ -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;
}

View file

@ -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)

View file

@ -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;

View file

@ -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) {

View file

@ -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;
vaddr = contigmalloc(size, M_DRM, M_NOWAIT, 0ul, maxaddr, align,
0);
*busaddr = vtophys(vaddr);
return vaddr;
dmah = malloc(sizeof(drm_dma_handle_t), M_DRM, M_ZERO | M_NOWAIT);
if (dmah == NULL)
return NULL;
#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);
}
/*@}*/

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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;

View file

@ -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)

View file

@ -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 */