mirror of
https://gitlab.freedesktop.org/mesa/drm.git
synced 2026-05-03 04:28:01 +02:00
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:
parent
31a06d0bac
commit
ec111d70fe
15 changed files with 233 additions and 160 deletions
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
/*@}*/
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue