mirror of
https://gitlab.freedesktop.org/mesa/drm.git
synced 2025-12-29 11:30:16 +01:00
Add PCI DMA memory functions and make addbufs_pci and associated code use
it. To do this we need to save the bus address along with the virtual
address in the seglist. Also fix some error handling and a few bits of
whitespace.
This commit is contained in:
parent
f2a0c5438d
commit
ce514e08aa
12 changed files with 378 additions and 158 deletions
|
|
@ -196,7 +196,8 @@ typedef struct drm_buf_entry {
|
|||
drm_buf_t *buflist;
|
||||
int seg_count;
|
||||
int page_order;
|
||||
unsigned long *seglist;
|
||||
vm_offset_t *seglist;
|
||||
dma_addr_t *seglist_bus;
|
||||
|
||||
drm_freelist_t freelist;
|
||||
} drm_buf_entry_t;
|
||||
|
|
@ -562,6 +563,12 @@ extern int DRM(sg_alloc)(DRM_IOCTL_ARGS);
|
|||
extern int DRM(sg_free)(DRM_IOCTL_ARGS);
|
||||
#endif
|
||||
|
||||
/* consistent PCI memory functions (drm_pci.h) */
|
||||
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);
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* _DRM_P_H_ */
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ int DRM(addmap)( DRM_IOCTL_ARGS )
|
|||
|
||||
case _DRM_SHM:
|
||||
map->handle = (void *)DRM(alloc)(map->size, DRM_MEM_SAREA);
|
||||
DRM_DEBUG( "%ld %d %p\n",
|
||||
DRM_DEBUG( "%lu %d %p\n",
|
||||
map->size, DRM(order)( map->size ), map->handle );
|
||||
if ( !map->handle ) {
|
||||
DRM(free)( map, sizeof(*map), DRM_MEM_MAPS );
|
||||
|
|
@ -279,31 +279,33 @@ int DRM(rmmap)( DRM_IOCTL_ARGS )
|
|||
#if __HAVE_DMA
|
||||
|
||||
|
||||
static void DRM(cleanup_buf_error)(drm_buf_entry_t *entry)
|
||||
static void DRM(cleanup_buf_error)(drm_device_t *dev, drm_buf_entry_t *entry)
|
||||
{
|
||||
int i;
|
||||
|
||||
#if __HAVE_PCI_DMA
|
||||
if (entry->seg_count) {
|
||||
for (i = 0; i < entry->seg_count; i++) {
|
||||
DRM(free)((void *)entry->seglist[i],
|
||||
entry->buf_size,
|
||||
DRM_MEM_DMA);
|
||||
if (entry->seglist[i] != NULL)
|
||||
DRM(pci_free)(dev, entry->buf_size,
|
||||
(void *)entry->seglist[i],
|
||||
entry->seglist_bus[i]);
|
||||
}
|
||||
DRM(free)(entry->seglist,
|
||||
entry->seg_count *
|
||||
sizeof(*entry->seglist),
|
||||
DRM_MEM_SEGS);
|
||||
DRM(free)(entry->seglist_bus, entry->seg_count *
|
||||
sizeof(*entry->seglist_bus), DRM_MEM_SEGS);
|
||||
|
||||
entry->seg_count = 0;
|
||||
}
|
||||
#endif /* __HAVE_PCI_DMA */
|
||||
|
||||
if(entry->buf_count) {
|
||||
for(i = 0; i < entry->buf_count; i++) {
|
||||
if(entry->buflist[i].dev_private) {
|
||||
DRM(free)(entry->buflist[i].dev_private,
|
||||
entry->buflist[i].dev_priv_size,
|
||||
DRM_MEM_BUFS);
|
||||
}
|
||||
if (entry->buf_count) {
|
||||
for (i = 0; i < entry->buf_count; i++) {
|
||||
DRM(free)(entry->buflist[i].dev_private,
|
||||
entry->buflist[i].dev_priv_size, DRM_MEM_BUFS);
|
||||
}
|
||||
DRM(free)(entry->buflist,
|
||||
entry->buf_count *
|
||||
|
|
@ -395,7 +397,9 @@ static int DRM(addbufs_agp)(drm_device_t *dev, drm_buf_desc_t *request)
|
|||
if(!buf->dev_private) {
|
||||
/* Set count correctly so we free the proper amount. */
|
||||
entry->buf_count = count;
|
||||
DRM(cleanup_buf_error)(entry);
|
||||
DRM(cleanup_buf_error)(dev, entry);
|
||||
DRM_UNLOCK;
|
||||
return DRM_ERR(ENOMEM);
|
||||
}
|
||||
memset( buf->dev_private, 0, buf->dev_priv_size );
|
||||
|
||||
|
|
@ -413,7 +417,7 @@ static int DRM(addbufs_agp)(drm_device_t *dev, drm_buf_desc_t *request)
|
|||
DRM_MEM_BUFS );
|
||||
if(!temp_buflist) {
|
||||
/* Free the entry because it isn't valid */
|
||||
DRM(cleanup_buf_error)(entry);
|
||||
DRM(cleanup_buf_error)(dev, entry);
|
||||
DRM_UNLOCK;
|
||||
return DRM_ERR(ENOMEM);
|
||||
}
|
||||
|
|
@ -450,7 +454,7 @@ static int DRM(addbufs_pci)(drm_device_t *dev, drm_buf_desc_t *request)
|
|||
int total;
|
||||
int page_order;
|
||||
drm_buf_entry_t *entry;
|
||||
unsigned long page;
|
||||
vm_offset_t vaddr;
|
||||
drm_buf_t *buf;
|
||||
int alignment;
|
||||
unsigned long offset;
|
||||
|
|
@ -459,6 +463,7 @@ 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);
|
||||
|
|
@ -482,42 +487,37 @@ static int DRM(addbufs_pci)(drm_device_t *dev, drm_buf_desc_t *request)
|
|||
return DRM_ERR(ENOMEM); /* May only call once for each order */
|
||||
}
|
||||
|
||||
entry->buflist = DRM(alloc)( count * sizeof(*entry->buflist),
|
||||
DRM_MEM_BUFS );
|
||||
if ( !entry->buflist ) {
|
||||
DRM_UNLOCK;
|
||||
return DRM_ERR(ENOMEM);
|
||||
}
|
||||
memset( entry->buflist, 0, count * sizeof(*entry->buflist) );
|
||||
entry->buflist = DRM(alloc)(count * sizeof(*entry->buflist),
|
||||
DRM_MEM_BUFS);
|
||||
entry->seglist = DRM(alloc)(count * sizeof(*entry->seglist),
|
||||
DRM_MEM_SEGS);
|
||||
entry->seglist_bus = DRM(alloc)(count * sizeof(*entry->seglist_bus),
|
||||
DRM_MEM_SEGS);
|
||||
|
||||
entry->seglist = DRM(alloc)( count * sizeof(*entry->seglist),
|
||||
DRM_MEM_SEGS );
|
||||
if ( !entry->seglist ) {
|
||||
DRM(free)( entry->buflist,
|
||||
count * sizeof(*entry->buflist),
|
||||
DRM_MEM_BUFS );
|
||||
DRM_UNLOCK;
|
||||
return DRM_ERR(ENOMEM);
|
||||
}
|
||||
memset( entry->seglist, 0, count * sizeof(*entry->seglist) );
|
||||
/* Keep the original pagelist until we know all the allocations
|
||||
* have succeeded
|
||||
*/
|
||||
temp_pagelist = DRM(alloc)((dma->page_count + (count << page_order)) *
|
||||
sizeof(*dma->pagelist), DRM_MEM_PAGES);
|
||||
|
||||
temp_pagelist = DRM(realloc)( dma->pagelist,
|
||||
dma->page_count * sizeof(*dma->pagelist),
|
||||
(dma->page_count + (count << page_order))
|
||||
* sizeof(*dma->pagelist),
|
||||
DRM_MEM_PAGES );
|
||||
if(!temp_pagelist) {
|
||||
DRM(free)( entry->buflist,
|
||||
count * sizeof(*entry->buflist),
|
||||
DRM_MEM_BUFS );
|
||||
DRM(free)( entry->seglist,
|
||||
count * sizeof(*entry->seglist),
|
||||
DRM_MEM_SEGS );
|
||||
if (entry->buflist == NULL || entry->seglist == NULL ||
|
||||
temp_pagelist == NULL) {
|
||||
DRM(free)(entry->buflist, count * sizeof(*entry->buflist),
|
||||
DRM_MEM_BUFS);
|
||||
DRM(free)(entry->seglist, count * sizeof(*entry->seglist),
|
||||
DRM_MEM_SEGS);
|
||||
DRM(free)(entry->seglist_bus, count *
|
||||
sizeof(*entry->seglist_bus), DRM_MEM_SEGS);
|
||||
DRM_UNLOCK;
|
||||
return DRM_ERR(ENOMEM);
|
||||
}
|
||||
|
||||
dma->pagelist = temp_pagelist;
|
||||
bzero(entry->buflist, count * sizeof(*entry->buflist));
|
||||
bzero(entry->seglist, count * sizeof(*entry->seglist));
|
||||
|
||||
memcpy(temp_pagelist, dma->pagelist, dma->page_count *
|
||||
sizeof(*dma->pagelist));
|
||||
|
||||
DRM_DEBUG( "pagelist: %d entries\n",
|
||||
dma->page_count + (count << page_order) );
|
||||
|
||||
|
|
@ -527,15 +527,28 @@ static int DRM(addbufs_pci)(drm_device_t *dev, drm_buf_desc_t *request)
|
|||
page_count = 0;
|
||||
|
||||
while ( entry->buf_count < count ) {
|
||||
page = (unsigned long)DRM(alloc)( size, DRM_MEM_DMA );
|
||||
if ( !page ) break;
|
||||
entry->seglist[entry->seg_count++] = page;
|
||||
vaddr = (vm_offset_t) DRM(pci_alloc)(dev, size, alignment,
|
||||
0xfffffffful, &bus_addr);
|
||||
if (vaddr == NULL) {
|
||||
/* Set count correctly so we free the proper amount. */
|
||||
entry->buf_count = count;
|
||||
entry->seg_count = count;
|
||||
DRM(cleanup_buf_error)(dev, entry);
|
||||
DRM(free)(temp_pagelist, (dma->page_count +
|
||||
(count << page_order)) * sizeof(*dma->pagelist),
|
||||
DRM_MEM_PAGES);
|
||||
DRM_UNLOCK;
|
||||
return DRM_ERR(ENOMEM);
|
||||
}
|
||||
|
||||
entry->seglist_bus[entry->seg_count] = bus_addr;
|
||||
entry->seglist[entry->seg_count++] = vaddr;
|
||||
for ( i = 0 ; i < (1 << page_order) ; i++ ) {
|
||||
DRM_DEBUG( "page %d @ 0x%08lx\n",
|
||||
dma->page_count + page_count,
|
||||
page + PAGE_SIZE * i );
|
||||
dma->pagelist[dma->page_count + page_count++]
|
||||
= page + PAGE_SIZE * i;
|
||||
temp_pagelist[dma->page_count + page_count++] =
|
||||
vaddr + PAGE_SIZE * i;
|
||||
}
|
||||
for ( offset = 0 ;
|
||||
offset + size <= total && entry->buf_count < count ;
|
||||
|
|
@ -546,10 +559,28 @@ 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 *)(page + offset);
|
||||
buf->address = (void *)(vaddr + offset);
|
||||
buf->bus_address = bus_addr + offset;
|
||||
buf->next = NULL;
|
||||
buf->pending = 0;
|
||||
buf->filp = NULL;
|
||||
|
||||
buf->dev_priv_size = sizeof(DRIVER_BUF_PRIV_T);
|
||||
buf->dev_private = DRM(alloc)(sizeof(DRIVER_BUF_PRIV_T),
|
||||
DRM_MEM_BUFS);
|
||||
if (buf->dev_private == NULL) {
|
||||
/* Set count correctly so we free the proper amount. */
|
||||
entry->buf_count = count;
|
||||
entry->seg_count = count;
|
||||
DRM(cleanup_buf_error)(dev, entry);
|
||||
DRM(free)(temp_pagelist, (dma->page_count +
|
||||
(count << page_order)) *
|
||||
sizeof(*dma->pagelist), DRM_MEM_PAGES );
|
||||
DRM_UNLOCK;
|
||||
return DRM_ERR(ENOMEM);
|
||||
}
|
||||
bzero(buf->dev_private, buf->dev_priv_size);
|
||||
|
||||
DRM_DEBUG( "buffer %d @ %p\n",
|
||||
entry->buf_count, buf->address );
|
||||
}
|
||||
|
|
@ -561,9 +592,12 @@ static int DRM(addbufs_pci)(drm_device_t *dev, drm_buf_desc_t *request)
|
|||
(dma->buf_count + entry->buf_count)
|
||||
* sizeof(*dma->buflist),
|
||||
DRM_MEM_BUFS );
|
||||
if(!temp_buflist) {
|
||||
if (temp_buflist == NULL) {
|
||||
/* Free the entry because it isn't valid */
|
||||
DRM(cleanup_buf_error)(entry);
|
||||
DRM(cleanup_buf_error)(dev, entry);
|
||||
DRM(free)(temp_pagelist, (dma->page_count +
|
||||
(count << page_order)) * sizeof(*dma->pagelist),
|
||||
DRM_MEM_PAGES);
|
||||
DRM_UNLOCK;
|
||||
return DRM_ERR(ENOMEM);
|
||||
}
|
||||
|
|
@ -573,6 +607,13 @@ static int DRM(addbufs_pci)(drm_device_t *dev, drm_buf_desc_t *request)
|
|||
dma->buflist[i + dma->buf_count] = &entry->buflist[i];
|
||||
}
|
||||
|
||||
/* No allocations failed, so now we can replace the orginal pagelist
|
||||
* with the new one.
|
||||
*/
|
||||
DRM(free)(dma->pagelist, dma->page_count * sizeof(*dma->pagelist),
|
||||
DRM_MEM_PAGES);
|
||||
dma->pagelist = temp_pagelist;
|
||||
|
||||
dma->buf_count += entry->buf_count;
|
||||
dma->seg_count += entry->seg_count;
|
||||
dma->page_count += entry->seg_count << page_order;
|
||||
|
|
@ -669,7 +710,7 @@ static int DRM(addbufs_sg)(drm_device_t *dev, drm_buf_desc_t *request)
|
|||
if(!buf->dev_private) {
|
||||
/* Set count correctly so we free the proper amount. */
|
||||
entry->buf_count = count;
|
||||
DRM(cleanup_buf_error)(entry);
|
||||
DRM(cleanup_buf_error)(dev, entry);
|
||||
DRM_UNLOCK;
|
||||
return DRM_ERR(ENOMEM);
|
||||
}
|
||||
|
|
@ -693,7 +734,7 @@ static int DRM(addbufs_sg)(drm_device_t *dev, drm_buf_desc_t *request)
|
|||
DRM_MEM_BUFS );
|
||||
if(!temp_buflist) {
|
||||
/* Free the entry because it isn't valid */
|
||||
DRM(cleanup_buf_error)(entry);
|
||||
DRM(cleanup_buf_error)(dev, entry);
|
||||
DRM_UNLOCK;
|
||||
return DRM_ERR(ENOMEM);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ void DRM(dma_takedown)(drm_device_t *dev)
|
|||
|
||||
/* Clear dma buffers */
|
||||
for (i = 0; i <= DRM_MAX_ORDER; i++) {
|
||||
#if __HAVE_PCI_DMA
|
||||
if (dma->bufs[i].seg_count) {
|
||||
DRM_DEBUG("order %d: buf_count = %d,"
|
||||
" seg_count = %d\n",
|
||||
|
|
@ -77,22 +78,27 @@ 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(free)((void *)dma->bufs[i].seglist[j],
|
||||
dma->bufs[i].buf_size,
|
||||
DRM_MEM_DMA);
|
||||
if (dma->bufs[i].seglist[j] != NULL)
|
||||
DRM(pci_free)(dev, dma->bufs[i].buf_size,
|
||||
(void *)dma->bufs[i].seglist[j],
|
||||
dma->bufs[i].seglist_bus[j]);
|
||||
}
|
||||
DRM(free)(dma->bufs[i].seglist,
|
||||
dma->bufs[i].seg_count
|
||||
* sizeof(*dma->bufs[0].seglist),
|
||||
DRM_MEM_SEGS);
|
||||
DRM(free)(dma->bufs[i].seglist_bus,
|
||||
dma->bufs[i].seg_count
|
||||
* sizeof(*dma->bufs[0].seglist_bus),
|
||||
DRM_MEM_SEGS);
|
||||
}
|
||||
if(dma->bufs[i].buf_count) {
|
||||
for(j = 0; j < dma->bufs[i].buf_count; j++) {
|
||||
if(dma->bufs[i].buflist[j].dev_private) {
|
||||
DRM(free)(dma->bufs[i].buflist[j].dev_private,
|
||||
#endif /* __HAVE_PCI_DMA */
|
||||
|
||||
if (dma->bufs[i].buf_count) {
|
||||
for (j = 0; j < dma->bufs[i].buf_count; j++) {
|
||||
DRM(free)(dma->bufs[i].buflist[j].dev_private,
|
||||
dma->bufs[i].buflist[j].dev_priv_size,
|
||||
DRM_MEM_BUFS);
|
||||
}
|
||||
}
|
||||
DRM(free)(dma->bufs[i].buflist,
|
||||
dma->bufs[i].buf_count *
|
||||
|
|
@ -101,17 +107,10 @@ void DRM(dma_takedown)(drm_device_t *dev)
|
|||
}
|
||||
}
|
||||
|
||||
if (dma->buflist) {
|
||||
DRM(free)(dma->buflist,
|
||||
dma->buf_count * sizeof(*dma->buflist),
|
||||
DRM_MEM_BUFS);
|
||||
}
|
||||
|
||||
if (dma->pagelist) {
|
||||
DRM(free)(dma->pagelist,
|
||||
dma->page_count * sizeof(*dma->pagelist),
|
||||
DRM_MEM_PAGES);
|
||||
}
|
||||
DRM(free)(dma->buflist, dma->buf_count * sizeof(*dma->buflist),
|
||||
DRM_MEM_BUFS);
|
||||
DRM(free)(dma->pagelist, dma->page_count * sizeof(*dma->pagelist),
|
||||
DRM_MEM_PAGES);
|
||||
DRM(free)(dev->dma, sizeof(*dev->dma), DRM_MEM_DRIVER);
|
||||
dev->dma = NULL;
|
||||
}
|
||||
|
|
|
|||
65
bsd-core/drm_pci.c
Normal file
65
bsd-core/drm_pci.c
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
/**
|
||||
* \file drm_pci.h
|
||||
* \brief PCI consistent, DMA-accessible memory functions.
|
||||
*
|
||||
* \author Eric Anholt <anholt@FreeBSD.org>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2003 Eric Anholt.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
|
||||
/**********************************************************************/
|
||||
/** \name PCI memory */
|
||||
/*@{*/
|
||||
|
||||
/**
|
||||
* \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)
|
||||
{
|
||||
void *vaddr;
|
||||
|
||||
vaddr = contigmalloc(size, DRM(M_DRM), M_WAITOK, 0ul, maxaddr, align,
|
||||
0);
|
||||
*busaddr = vtophys(vaddr);
|
||||
|
||||
return vaddr;
|
||||
}
|
||||
|
||||
/**
|
||||
* \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)
|
||||
{
|
||||
#if __FreeBSD_version > 500000
|
||||
contigfree(vaddr, size, DRM(M_DRM)); /* Not available on 4.x */
|
||||
#endif
|
||||
}
|
||||
|
||||
/*@}*/
|
||||
|
|
@ -75,11 +75,10 @@ drm_chipinfo_t DRM(devicelist)[] = {
|
|||
#include "drm_ioctl.h"
|
||||
#include "drm_lock.h"
|
||||
#include "drm_memory.h"
|
||||
#include "drm_pci.h"
|
||||
#include "drm_sysctl.h"
|
||||
#include "drm_vm.h"
|
||||
#if __HAVE_SG
|
||||
#include "drm_scatter.h"
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
DRIVER_MODULE(r128, pci, r128_driver, r128_devclass, 0, 0);
|
||||
|
|
|
|||
|
|
@ -88,11 +88,10 @@ drm_chipinfo_t DRM(devicelist)[] = {
|
|||
#include "drm_ioctl.h"
|
||||
#include "drm_lock.h"
|
||||
#include "drm_memory.h"
|
||||
#include "drm_pci.h"
|
||||
#include "drm_vm.h"
|
||||
#include "drm_sysctl.h"
|
||||
#if __HAVE_SG
|
||||
#include "drm_scatter.h"
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
DRIVER_MODULE(DRIVER_NAME, pci, DRM(driver), DRM(devclass), 0, 0);
|
||||
|
|
|
|||
|
|
@ -196,7 +196,8 @@ typedef struct drm_buf_entry {
|
|||
drm_buf_t *buflist;
|
||||
int seg_count;
|
||||
int page_order;
|
||||
unsigned long *seglist;
|
||||
vm_offset_t *seglist;
|
||||
dma_addr_t *seglist_bus;
|
||||
|
||||
drm_freelist_t freelist;
|
||||
} drm_buf_entry_t;
|
||||
|
|
@ -562,6 +563,12 @@ extern int DRM(sg_alloc)(DRM_IOCTL_ARGS);
|
|||
extern int DRM(sg_free)(DRM_IOCTL_ARGS);
|
||||
#endif
|
||||
|
||||
/* consistent PCI memory functions (drm_pci.h) */
|
||||
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);
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* _DRM_P_H_ */
|
||||
|
|
|
|||
151
bsd/drm_bufs.h
151
bsd/drm_bufs.h
|
|
@ -141,7 +141,7 @@ int DRM(addmap)( DRM_IOCTL_ARGS )
|
|||
|
||||
case _DRM_SHM:
|
||||
map->handle = (void *)DRM(alloc)(map->size, DRM_MEM_SAREA);
|
||||
DRM_DEBUG( "%ld %d %p\n",
|
||||
DRM_DEBUG( "%lu %d %p\n",
|
||||
map->size, DRM(order)( map->size ), map->handle );
|
||||
if ( !map->handle ) {
|
||||
DRM(free)( map, sizeof(*map), DRM_MEM_MAPS );
|
||||
|
|
@ -279,31 +279,33 @@ int DRM(rmmap)( DRM_IOCTL_ARGS )
|
|||
#if __HAVE_DMA
|
||||
|
||||
|
||||
static void DRM(cleanup_buf_error)(drm_buf_entry_t *entry)
|
||||
static void DRM(cleanup_buf_error)(drm_device_t *dev, drm_buf_entry_t *entry)
|
||||
{
|
||||
int i;
|
||||
|
||||
#if __HAVE_PCI_DMA
|
||||
if (entry->seg_count) {
|
||||
for (i = 0; i < entry->seg_count; i++) {
|
||||
DRM(free)((void *)entry->seglist[i],
|
||||
entry->buf_size,
|
||||
DRM_MEM_DMA);
|
||||
if (entry->seglist[i] != NULL)
|
||||
DRM(pci_free)(dev, entry->buf_size,
|
||||
(void *)entry->seglist[i],
|
||||
entry->seglist_bus[i]);
|
||||
}
|
||||
DRM(free)(entry->seglist,
|
||||
entry->seg_count *
|
||||
sizeof(*entry->seglist),
|
||||
DRM_MEM_SEGS);
|
||||
DRM(free)(entry->seglist_bus, entry->seg_count *
|
||||
sizeof(*entry->seglist_bus), DRM_MEM_SEGS);
|
||||
|
||||
entry->seg_count = 0;
|
||||
}
|
||||
#endif /* __HAVE_PCI_DMA */
|
||||
|
||||
if(entry->buf_count) {
|
||||
for(i = 0; i < entry->buf_count; i++) {
|
||||
if(entry->buflist[i].dev_private) {
|
||||
DRM(free)(entry->buflist[i].dev_private,
|
||||
entry->buflist[i].dev_priv_size,
|
||||
DRM_MEM_BUFS);
|
||||
}
|
||||
if (entry->buf_count) {
|
||||
for (i = 0; i < entry->buf_count; i++) {
|
||||
DRM(free)(entry->buflist[i].dev_private,
|
||||
entry->buflist[i].dev_priv_size, DRM_MEM_BUFS);
|
||||
}
|
||||
DRM(free)(entry->buflist,
|
||||
entry->buf_count *
|
||||
|
|
@ -395,7 +397,9 @@ static int DRM(addbufs_agp)(drm_device_t *dev, drm_buf_desc_t *request)
|
|||
if(!buf->dev_private) {
|
||||
/* Set count correctly so we free the proper amount. */
|
||||
entry->buf_count = count;
|
||||
DRM(cleanup_buf_error)(entry);
|
||||
DRM(cleanup_buf_error)(dev, entry);
|
||||
DRM_UNLOCK;
|
||||
return DRM_ERR(ENOMEM);
|
||||
}
|
||||
memset( buf->dev_private, 0, buf->dev_priv_size );
|
||||
|
||||
|
|
@ -413,7 +417,7 @@ static int DRM(addbufs_agp)(drm_device_t *dev, drm_buf_desc_t *request)
|
|||
DRM_MEM_BUFS );
|
||||
if(!temp_buflist) {
|
||||
/* Free the entry because it isn't valid */
|
||||
DRM(cleanup_buf_error)(entry);
|
||||
DRM(cleanup_buf_error)(dev, entry);
|
||||
DRM_UNLOCK;
|
||||
return DRM_ERR(ENOMEM);
|
||||
}
|
||||
|
|
@ -450,7 +454,7 @@ static int DRM(addbufs_pci)(drm_device_t *dev, drm_buf_desc_t *request)
|
|||
int total;
|
||||
int page_order;
|
||||
drm_buf_entry_t *entry;
|
||||
unsigned long page;
|
||||
vm_offset_t vaddr;
|
||||
drm_buf_t *buf;
|
||||
int alignment;
|
||||
unsigned long offset;
|
||||
|
|
@ -459,6 +463,7 @@ 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);
|
||||
|
|
@ -482,42 +487,37 @@ static int DRM(addbufs_pci)(drm_device_t *dev, drm_buf_desc_t *request)
|
|||
return DRM_ERR(ENOMEM); /* May only call once for each order */
|
||||
}
|
||||
|
||||
entry->buflist = DRM(alloc)( count * sizeof(*entry->buflist),
|
||||
DRM_MEM_BUFS );
|
||||
if ( !entry->buflist ) {
|
||||
DRM_UNLOCK;
|
||||
return DRM_ERR(ENOMEM);
|
||||
}
|
||||
memset( entry->buflist, 0, count * sizeof(*entry->buflist) );
|
||||
entry->buflist = DRM(alloc)(count * sizeof(*entry->buflist),
|
||||
DRM_MEM_BUFS);
|
||||
entry->seglist = DRM(alloc)(count * sizeof(*entry->seglist),
|
||||
DRM_MEM_SEGS);
|
||||
entry->seglist_bus = DRM(alloc)(count * sizeof(*entry->seglist_bus),
|
||||
DRM_MEM_SEGS);
|
||||
|
||||
entry->seglist = DRM(alloc)( count * sizeof(*entry->seglist),
|
||||
DRM_MEM_SEGS );
|
||||
if ( !entry->seglist ) {
|
||||
DRM(free)( entry->buflist,
|
||||
count * sizeof(*entry->buflist),
|
||||
DRM_MEM_BUFS );
|
||||
DRM_UNLOCK;
|
||||
return DRM_ERR(ENOMEM);
|
||||
}
|
||||
memset( entry->seglist, 0, count * sizeof(*entry->seglist) );
|
||||
/* Keep the original pagelist until we know all the allocations
|
||||
* have succeeded
|
||||
*/
|
||||
temp_pagelist = DRM(alloc)((dma->page_count + (count << page_order)) *
|
||||
sizeof(*dma->pagelist), DRM_MEM_PAGES);
|
||||
|
||||
temp_pagelist = DRM(realloc)( dma->pagelist,
|
||||
dma->page_count * sizeof(*dma->pagelist),
|
||||
(dma->page_count + (count << page_order))
|
||||
* sizeof(*dma->pagelist),
|
||||
DRM_MEM_PAGES );
|
||||
if(!temp_pagelist) {
|
||||
DRM(free)( entry->buflist,
|
||||
count * sizeof(*entry->buflist),
|
||||
DRM_MEM_BUFS );
|
||||
DRM(free)( entry->seglist,
|
||||
count * sizeof(*entry->seglist),
|
||||
DRM_MEM_SEGS );
|
||||
if (entry->buflist == NULL || entry->seglist == NULL ||
|
||||
temp_pagelist == NULL) {
|
||||
DRM(free)(entry->buflist, count * sizeof(*entry->buflist),
|
||||
DRM_MEM_BUFS);
|
||||
DRM(free)(entry->seglist, count * sizeof(*entry->seglist),
|
||||
DRM_MEM_SEGS);
|
||||
DRM(free)(entry->seglist_bus, count *
|
||||
sizeof(*entry->seglist_bus), DRM_MEM_SEGS);
|
||||
DRM_UNLOCK;
|
||||
return DRM_ERR(ENOMEM);
|
||||
}
|
||||
|
||||
dma->pagelist = temp_pagelist;
|
||||
bzero(entry->buflist, count * sizeof(*entry->buflist));
|
||||
bzero(entry->seglist, count * sizeof(*entry->seglist));
|
||||
|
||||
memcpy(temp_pagelist, dma->pagelist, dma->page_count *
|
||||
sizeof(*dma->pagelist));
|
||||
|
||||
DRM_DEBUG( "pagelist: %d entries\n",
|
||||
dma->page_count + (count << page_order) );
|
||||
|
||||
|
|
@ -527,15 +527,28 @@ static int DRM(addbufs_pci)(drm_device_t *dev, drm_buf_desc_t *request)
|
|||
page_count = 0;
|
||||
|
||||
while ( entry->buf_count < count ) {
|
||||
page = (unsigned long)DRM(alloc)( size, DRM_MEM_DMA );
|
||||
if ( !page ) break;
|
||||
entry->seglist[entry->seg_count++] = page;
|
||||
vaddr = (vm_offset_t) DRM(pci_alloc)(dev, size, alignment,
|
||||
0xfffffffful, &bus_addr);
|
||||
if (vaddr == NULL) {
|
||||
/* Set count correctly so we free the proper amount. */
|
||||
entry->buf_count = count;
|
||||
entry->seg_count = count;
|
||||
DRM(cleanup_buf_error)(dev, entry);
|
||||
DRM(free)(temp_pagelist, (dma->page_count +
|
||||
(count << page_order)) * sizeof(*dma->pagelist),
|
||||
DRM_MEM_PAGES);
|
||||
DRM_UNLOCK;
|
||||
return DRM_ERR(ENOMEM);
|
||||
}
|
||||
|
||||
entry->seglist_bus[entry->seg_count] = bus_addr;
|
||||
entry->seglist[entry->seg_count++] = vaddr;
|
||||
for ( i = 0 ; i < (1 << page_order) ; i++ ) {
|
||||
DRM_DEBUG( "page %d @ 0x%08lx\n",
|
||||
dma->page_count + page_count,
|
||||
page + PAGE_SIZE * i );
|
||||
dma->pagelist[dma->page_count + page_count++]
|
||||
= page + PAGE_SIZE * i;
|
||||
temp_pagelist[dma->page_count + page_count++] =
|
||||
vaddr + PAGE_SIZE * i;
|
||||
}
|
||||
for ( offset = 0 ;
|
||||
offset + size <= total && entry->buf_count < count ;
|
||||
|
|
@ -546,10 +559,28 @@ 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 *)(page + offset);
|
||||
buf->address = (void *)(vaddr + offset);
|
||||
buf->bus_address = bus_addr + offset;
|
||||
buf->next = NULL;
|
||||
buf->pending = 0;
|
||||
buf->filp = NULL;
|
||||
|
||||
buf->dev_priv_size = sizeof(DRIVER_BUF_PRIV_T);
|
||||
buf->dev_private = DRM(alloc)(sizeof(DRIVER_BUF_PRIV_T),
|
||||
DRM_MEM_BUFS);
|
||||
if (buf->dev_private == NULL) {
|
||||
/* Set count correctly so we free the proper amount. */
|
||||
entry->buf_count = count;
|
||||
entry->seg_count = count;
|
||||
DRM(cleanup_buf_error)(dev, entry);
|
||||
DRM(free)(temp_pagelist, (dma->page_count +
|
||||
(count << page_order)) *
|
||||
sizeof(*dma->pagelist), DRM_MEM_PAGES );
|
||||
DRM_UNLOCK;
|
||||
return DRM_ERR(ENOMEM);
|
||||
}
|
||||
bzero(buf->dev_private, buf->dev_priv_size);
|
||||
|
||||
DRM_DEBUG( "buffer %d @ %p\n",
|
||||
entry->buf_count, buf->address );
|
||||
}
|
||||
|
|
@ -561,9 +592,12 @@ static int DRM(addbufs_pci)(drm_device_t *dev, drm_buf_desc_t *request)
|
|||
(dma->buf_count + entry->buf_count)
|
||||
* sizeof(*dma->buflist),
|
||||
DRM_MEM_BUFS );
|
||||
if(!temp_buflist) {
|
||||
if (temp_buflist == NULL) {
|
||||
/* Free the entry because it isn't valid */
|
||||
DRM(cleanup_buf_error)(entry);
|
||||
DRM(cleanup_buf_error)(dev, entry);
|
||||
DRM(free)(temp_pagelist, (dma->page_count +
|
||||
(count << page_order)) * sizeof(*dma->pagelist),
|
||||
DRM_MEM_PAGES);
|
||||
DRM_UNLOCK;
|
||||
return DRM_ERR(ENOMEM);
|
||||
}
|
||||
|
|
@ -573,6 +607,13 @@ static int DRM(addbufs_pci)(drm_device_t *dev, drm_buf_desc_t *request)
|
|||
dma->buflist[i + dma->buf_count] = &entry->buflist[i];
|
||||
}
|
||||
|
||||
/* No allocations failed, so now we can replace the orginal pagelist
|
||||
* with the new one.
|
||||
*/
|
||||
DRM(free)(dma->pagelist, dma->page_count * sizeof(*dma->pagelist),
|
||||
DRM_MEM_PAGES);
|
||||
dma->pagelist = temp_pagelist;
|
||||
|
||||
dma->buf_count += entry->buf_count;
|
||||
dma->seg_count += entry->seg_count;
|
||||
dma->page_count += entry->seg_count << page_order;
|
||||
|
|
@ -669,7 +710,7 @@ static int DRM(addbufs_sg)(drm_device_t *dev, drm_buf_desc_t *request)
|
|||
if(!buf->dev_private) {
|
||||
/* Set count correctly so we free the proper amount. */
|
||||
entry->buf_count = count;
|
||||
DRM(cleanup_buf_error)(entry);
|
||||
DRM(cleanup_buf_error)(dev, entry);
|
||||
DRM_UNLOCK;
|
||||
return DRM_ERR(ENOMEM);
|
||||
}
|
||||
|
|
@ -693,7 +734,7 @@ static int DRM(addbufs_sg)(drm_device_t *dev, drm_buf_desc_t *request)
|
|||
DRM_MEM_BUFS );
|
||||
if(!temp_buflist) {
|
||||
/* Free the entry because it isn't valid */
|
||||
DRM(cleanup_buf_error)(entry);
|
||||
DRM(cleanup_buf_error)(dev, entry);
|
||||
DRM_UNLOCK;
|
||||
return DRM_ERR(ENOMEM);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ void DRM(dma_takedown)(drm_device_t *dev)
|
|||
|
||||
/* Clear dma buffers */
|
||||
for (i = 0; i <= DRM_MAX_ORDER; i++) {
|
||||
#if __HAVE_PCI_DMA
|
||||
if (dma->bufs[i].seg_count) {
|
||||
DRM_DEBUG("order %d: buf_count = %d,"
|
||||
" seg_count = %d\n",
|
||||
|
|
@ -77,22 +78,27 @@ 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(free)((void *)dma->bufs[i].seglist[j],
|
||||
dma->bufs[i].buf_size,
|
||||
DRM_MEM_DMA);
|
||||
if (dma->bufs[i].seglist[j] != NULL)
|
||||
DRM(pci_free)(dev, dma->bufs[i].buf_size,
|
||||
(void *)dma->bufs[i].seglist[j],
|
||||
dma->bufs[i].seglist_bus[j]);
|
||||
}
|
||||
DRM(free)(dma->bufs[i].seglist,
|
||||
dma->bufs[i].seg_count
|
||||
* sizeof(*dma->bufs[0].seglist),
|
||||
DRM_MEM_SEGS);
|
||||
DRM(free)(dma->bufs[i].seglist_bus,
|
||||
dma->bufs[i].seg_count
|
||||
* sizeof(*dma->bufs[0].seglist_bus),
|
||||
DRM_MEM_SEGS);
|
||||
}
|
||||
if(dma->bufs[i].buf_count) {
|
||||
for(j = 0; j < dma->bufs[i].buf_count; j++) {
|
||||
if(dma->bufs[i].buflist[j].dev_private) {
|
||||
DRM(free)(dma->bufs[i].buflist[j].dev_private,
|
||||
#endif /* __HAVE_PCI_DMA */
|
||||
|
||||
if (dma->bufs[i].buf_count) {
|
||||
for (j = 0; j < dma->bufs[i].buf_count; j++) {
|
||||
DRM(free)(dma->bufs[i].buflist[j].dev_private,
|
||||
dma->bufs[i].buflist[j].dev_priv_size,
|
||||
DRM_MEM_BUFS);
|
||||
}
|
||||
}
|
||||
DRM(free)(dma->bufs[i].buflist,
|
||||
dma->bufs[i].buf_count *
|
||||
|
|
@ -101,17 +107,10 @@ void DRM(dma_takedown)(drm_device_t *dev)
|
|||
}
|
||||
}
|
||||
|
||||
if (dma->buflist) {
|
||||
DRM(free)(dma->buflist,
|
||||
dma->buf_count * sizeof(*dma->buflist),
|
||||
DRM_MEM_BUFS);
|
||||
}
|
||||
|
||||
if (dma->pagelist) {
|
||||
DRM(free)(dma->pagelist,
|
||||
dma->page_count * sizeof(*dma->pagelist),
|
||||
DRM_MEM_PAGES);
|
||||
}
|
||||
DRM(free)(dma->buflist, dma->buf_count * sizeof(*dma->buflist),
|
||||
DRM_MEM_BUFS);
|
||||
DRM(free)(dma->pagelist, dma->page_count * sizeof(*dma->pagelist),
|
||||
DRM_MEM_PAGES);
|
||||
DRM(free)(dev->dma, sizeof(*dev->dma), DRM_MEM_DRIVER);
|
||||
dev->dma = NULL;
|
||||
}
|
||||
|
|
|
|||
65
bsd/drm_pci.h
Normal file
65
bsd/drm_pci.h
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
/**
|
||||
* \file drm_pci.h
|
||||
* \brief PCI consistent, DMA-accessible memory functions.
|
||||
*
|
||||
* \author Eric Anholt <anholt@FreeBSD.org>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2003 Eric Anholt.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
|
||||
/**********************************************************************/
|
||||
/** \name PCI memory */
|
||||
/*@{*/
|
||||
|
||||
/**
|
||||
* \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)
|
||||
{
|
||||
void *vaddr;
|
||||
|
||||
vaddr = contigmalloc(size, DRM(M_DRM), M_WAITOK, 0ul, maxaddr, align,
|
||||
0);
|
||||
*busaddr = vtophys(vaddr);
|
||||
|
||||
return vaddr;
|
||||
}
|
||||
|
||||
/**
|
||||
* \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)
|
||||
{
|
||||
#if __FreeBSD_version > 500000
|
||||
contigfree(vaddr, size, DRM(M_DRM)); /* Not available on 4.x */
|
||||
#endif
|
||||
}
|
||||
|
||||
/*@}*/
|
||||
|
|
@ -75,11 +75,10 @@ drm_chipinfo_t DRM(devicelist)[] = {
|
|||
#include "drm_ioctl.h"
|
||||
#include "drm_lock.h"
|
||||
#include "drm_memory.h"
|
||||
#include "drm_pci.h"
|
||||
#include "drm_sysctl.h"
|
||||
#include "drm_vm.h"
|
||||
#if __HAVE_SG
|
||||
#include "drm_scatter.h"
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
DRIVER_MODULE(r128, pci, r128_driver, r128_devclass, 0, 0);
|
||||
|
|
|
|||
|
|
@ -88,11 +88,10 @@ drm_chipinfo_t DRM(devicelist)[] = {
|
|||
#include "drm_ioctl.h"
|
||||
#include "drm_lock.h"
|
||||
#include "drm_memory.h"
|
||||
#include "drm_pci.h"
|
||||
#include "drm_vm.h"
|
||||
#include "drm_sysctl.h"
|
||||
#if __HAVE_SG
|
||||
#include "drm_scatter.h"
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
DRIVER_MODULE(DRIVER_NAME, pci, DRM(driver), DRM(devclass), 0, 0);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue