First audit of PCI GART code. Implementation appears to be solid on x86

platforms, still need to fix PPC?
This commit is contained in:
Gareth Hughes 2001-01-23 13:06:19 +00:00
parent c11d39c2e1
commit 967a589abd
11 changed files with 136 additions and 203 deletions

View file

@ -37,7 +37,7 @@
#define R128_NAME "r128"
#define R128_DESC "ATI Rage 128"
#define R128_DATE "20010101"
#define R128_DATE "20010123"
#define R128_MAJOR 2
#define R128_MINOR 1
#define R128_PATCHLEVEL 4
@ -312,7 +312,7 @@ static int r128_takedown(drm_device_t *dev)
handled in the AGP/GART driver. */
break;
case _DRM_SCATTER_GATHER:
if(dev->sg) {
if (dev->sg) {
drm_sg_cleanup(dev->sg);
dev->sg = NULL;
}

View file

@ -23,7 +23,7 @@
# 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.
#
#
#
# ***** NOTE NOTE NOTE NOTE NOTE *****
# To override the automatic Linux source tree determination, pass the
@ -47,7 +47,7 @@
# **** End of SMP/MODVERSIONS detection
CC= gcc
MODS= gamma.o tdfx.o
MODS= gamma.o tdfx.o r128.o
LIBS= libdrm.a
DRMOBJS= init.o memory.o proc.o auth.o context.o drawable.o bufs.o \
@ -129,7 +129,7 @@ endif
ifeq ($(AGP),1)
MODCFLAGS += -DCONFIG_AGP -DCONFIG_AGP_MODULE
DRMOBJS += agpsupport.o
MODS += mga.o r128.o radeon.o
MODS += mga.o radeon.o
ifeq ($(MACHINE),i386)
MODS += i810.o
endif

View file

@ -11,11 +11,11 @@
* 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
@ -23,7 +23,7 @@
* 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.
*
*
* Authors:
* Rickard E. (Rik) Faith <faith@valinux.com>
*
@ -51,7 +51,7 @@ int drm_addmap(struct inode *inode, struct file *filp, unsigned int cmd,
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->dev;
drm_map_t *map;
if (!(filp->f_mode & 3)) return -EACCES; /* Require read/write */
map = drm_alloc(sizeof(*map), DRM_MEM_MAPS);
@ -89,7 +89,7 @@ int drm_addmap(struct inode *inode, struct file *filp, unsigned int cmd,
#endif
map->handle = drm_ioremap(map->offset, map->size);
break;
case _DRM_SHM:
map->handle = (void *)drm_alloc_pages(drm_order(map->size)
@ -112,7 +112,10 @@ int drm_addmap(struct inode *inode, struct file *filp, unsigned int cmd,
break;
#endif
case _DRM_SCATTER_GATHER:
if(!dev->sg) return -EINVAL;
if (!dev->sg) {
drm_free(map, sizeof(*map), DRM_MEM_MAPS);
return -EINVAL;
}
map->offset = map->offset + dev->sg->handle;
break;
default:
@ -144,7 +147,7 @@ int drm_addmap(struct inode *inode, struct file *filp, unsigned int cmd,
&map->offset,
sizeof(map->offset)))
return -EFAULT;
}
}
return 0;
}
@ -179,7 +182,7 @@ int drm_addbufs(struct inode *inode, struct file *filp, unsigned int cmd,
count = request.count;
order = drm_order(request.size);
size = 1 << order;
DRM_DEBUG("count = %d, size = %d (%d), order = %d, queue_count = %d\n",
request.count, request.size, size, order, dev->queue_count);
@ -197,7 +200,7 @@ int drm_addbufs(struct inode *inode, struct file *filp, unsigned int cmd,
}
atomic_inc(&dev->buf_alloc);
spin_unlock(&dev->count_lock);
down(&dev->struct_sem);
entry = &dma->bufs[order];
if (entry->buf_count) {
@ -205,7 +208,7 @@ int drm_addbufs(struct inode *inode, struct file *filp, unsigned int cmd,
atomic_dec(&dev->buf_alloc);
return -ENOMEM; /* May only call once for each order */
}
entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
DRM_MEM_BUFS);
if (!entry->buflist) {
@ -289,12 +292,12 @@ int drm_addbufs(struct inode *inode, struct file *filp, unsigned int cmd,
dma->seg_count += entry->seg_count;
dma->page_count += entry->seg_count << page_order;
dma->byte_count += PAGE_SIZE * (entry->seg_count << page_order);
drm_freelist_create(&entry->freelist, entry->buf_count);
for (i = 0; i < entry->buf_count; i++) {
drm_freelist_put(dev, &entry->freelist, &entry->buflist[i]);
}
up(&dev->struct_sem);
request.count = entry->buf_count;
@ -304,7 +307,7 @@ int drm_addbufs(struct inode *inode, struct file *filp, unsigned int cmd,
&request,
sizeof(request)))
return -EFAULT;
atomic_dec(&dev->buf_alloc);
return 0;
}
@ -337,9 +340,9 @@ int drm_infobufs(struct inode *inode, struct file *filp, unsigned int cmd,
for (i = 0, count = 0; i < DRM_MAX_ORDER+1; i++) {
if (dma->bufs[i].buf_count) ++count;
}
DRM_DEBUG("count = %d\n", count);
if (request.count >= count) {
for (i = 0, count = 0; i < DRM_MAX_ORDER+1; i++) {
if (dma->bufs[i].buf_count) {
@ -379,7 +382,7 @@ int drm_infobufs(struct inode *inode, struct file *filp, unsigned int cmd,
&request,
sizeof(request)))
return -EFAULT;
return 0;
}
@ -413,7 +416,7 @@ int drm_markbufs(struct inode *inode, struct file *filp, unsigned int cmd,
entry->freelist.low_mark = request.low_mark;
entry->freelist.high_mark = request.high_mark;
return 0;
}
@ -454,7 +457,7 @@ int drm_freebufs(struct inode *inode, struct file *filp, unsigned int cmd,
}
drm_free_buffer(dev, buf);
}
return 0;
}
@ -472,7 +475,7 @@ int drm_mapbufs(struct inode *inode, struct file *filp, unsigned int cmd,
int i;
if (!dma) return -EINVAL;
DRM_DEBUG("\n");
spin_lock(&dev->count_lock);

View file

@ -351,16 +351,16 @@ int r128_addbufs(struct inode *inode, struct file *filp, unsigned int cmd,
return -EINVAL;
if (!dev_priv->is_pci && (request.flags & _DRM_SG_BUFFER))
return -EINVAL;
if (request.flags & _DRM_AGP_BUFFER)
#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
if (request.flags & _DRM_AGP_BUFFER)
return r128_addbufs_agp(inode, filp, cmd, arg);
#else
printk("WARNING: trying to use AGP without kernel support!\n");
#endif
if (request.flags & _DRM_SG_BUFFER)
if (request.flags & _DRM_SG_BUFFER) {
return r128_addbufs_sg(inode, filp, cmd, arg);
else
} else {
return -EINVAL;
}
}
int r128_mapbufs(struct inode *inode, struct file *filp, unsigned int cmd,

View file

@ -342,15 +342,13 @@ static void r128_cce_init_ring_buffer( drm_device_t *dev )
/* The manual (p. 2) says this address is in "VM space". This
* means it's an offset from the start of AGP space.
*/
if ( !dev_priv->is_pci ) {
#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
if ( !dev_priv->is_pci )
ring_start = dev_priv->cce_ring->offset - dev->agp->base;
#else
printk("WARNING: Trying to use AGP without kernel support!\n");
else
#endif
} else {
ring_start = dev_priv->cce_ring->offset - dev->sg->handle;
}
R128_WRITE( R128_PM4_BUFFER_OFFSET, ring_start | R128_AGP_OFFSET );
R128_WRITE( R128_PM4_BUFFER_DL_WPTR, 0 );
@ -405,12 +403,8 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
dev_priv->is_pci = init->is_pci;
/* GH: We don't support PCI cards until PCI GART is implemented.
* Fail here so we can remove all checks for PCI cards around
* the CCE ring code.
*/
if ( dev_priv->is_pci && !dev->sg) {
if ( dev_priv->is_pci && !dev->sg ) {
DRM_ERROR( "PCI GART memory not allocated!\n" );
drm_free( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
dev->dev_private = NULL;
return -EINVAL;
@ -511,21 +505,25 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
(drm_r128_sarea_t *)((u8 *)dev_priv->sarea->handle +
init->sarea_priv_offset);
if(dev_priv->is_pci) {
dev_priv->cce_ring->handle =
(void *)dev_priv->cce_ring->offset;
dev_priv->ring_rptr->handle =
(void *)dev_priv->ring_rptr->offset;
dev_priv->buffers->handle = (void *)dev_priv->buffers->offset;
} else {
if ( !dev_priv->is_pci ) {
DO_IOREMAP( dev_priv->cce_ring );
DO_IOREMAP( dev_priv->ring_rptr );
DO_IOREMAP( dev_priv->buffers );
} else {
dev_priv->cce_ring->handle =
(void *)dev_priv->cce_ring->offset;
dev_priv->ring_rptr->handle =
(void *)dev_priv->ring_rptr->offset;
dev_priv->buffers->handle = (void *)dev_priv->buffers->offset;
}
if ( !dev_priv->is_pci ) {
DO_IOREMAP( dev_priv->agp_textures );
}
#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
if ( !dev_priv->is_pci )
dev_priv->cce_buffers_offset = dev->agp->base;
else
#endif
dev_priv->cce_buffers_offset = dev->sg->handle;
dev_priv->ring.head = ((__volatile__ u32 *)
dev_priv->ring_rptr->handle);
@ -546,10 +544,9 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
R128_WRITE( R128_LAST_DISPATCH_REG,
dev_priv->sarea_priv->last_dispatch );
if ( dev_priv->is_pci && r128_pcigart_init( dev ) < 0) {
DRM_ERROR( "failed to init PCIGART!\n" );
drm_free( dev_priv, sizeof(*dev_priv),
DRM_MEM_DRIVER );
if ( dev_priv->is_pci && r128_pcigart_init( dev ) < 0 ) {
DRM_ERROR( "failed to init PCI GART!\n" );
drm_free( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
dev->dev_private = NULL;
return -EINVAL;
}
@ -611,10 +608,10 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
r128_do_wait_for_idle( dev_priv );
r128_do_engine_reset( dev );
r128_do_wait_for_idle( dev_priv );
r128_do_wait_for_idle( dev_priv );
}
#endif
return 0;
}
@ -623,15 +620,14 @@ static int r128_do_cleanup_cce( drm_device_t *dev )
if ( dev->dev_private ) {
drm_r128_private_t *dev_priv = dev->dev_private;
if(!dev_priv->is_pci) {
if ( !dev_priv->is_pci ) {
DO_IOREMAPFREE( dev_priv->cce_ring );
DO_IOREMAPFREE( dev_priv->ring_rptr );
DO_IOREMAPFREE( dev_priv->buffers );
DO_IOREMAPFREE( dev_priv->agp_textures );
} else {
r128_pcigart_cleanup( dev );
}
r128_pcigart_cleanup(dev);
drm_free( dev->dev_private, sizeof(drm_r128_private_t),
DRM_MEM_DRIVER );
dev->dev_private = NULL;

View file

@ -37,7 +37,7 @@
#define R128_NAME "r128"
#define R128_DESC "ATI Rage 128"
#define R128_DATE "20010101"
#define R128_DATE "20010123"
#define R128_MAJOR 2
#define R128_MINOR 1
#define R128_PATCHLEVEL 4
@ -312,7 +312,7 @@ static int r128_takedown(drm_device_t *dev)
handled in the AGP/GART driver. */
break;
case _DRM_SCATTER_GATHER:
if(dev->sg) {
if (dev->sg) {
drm_sg_cleanup(dev->sg);
dev->sg = NULL;
}

View file

@ -62,6 +62,7 @@ typedef struct drm_r128_private {
int cce_fifo_size;
int cce_secure;
int cce_running;
u32 cce_buffers_offset;
drm_r128_freelist_t *head;
drm_r128_freelist_t *tail;
@ -92,8 +93,7 @@ typedef struct drm_r128_private {
u32 depth_pitch_offset_c;
u32 span_pitch_offset_c;
void *pci_gart_page;
unsigned long phys_pci_gart_page;
unsigned long phys_pci_gart;
drm_map_t *sarea;
drm_map_t *fb;
@ -404,14 +404,17 @@ extern int r128_pcigart_init(drm_device_t *dev);
#define R128_WATERMARK_N 8
#define R128_WATERMARK_K 128
#define R128_MAX_USEC_TIMEOUT 100000 /* 100 ms */
#define R128_MAX_USEC_TIMEOUT 100000 /* 100 ms */
#define R128_LAST_FRAME_REG R128_GUI_SCRATCH_REG0
#define R128_LAST_DISPATCH_REG R128_GUI_SCRATCH_REG1
#define R128_MAX_VB_AGE 0x7fffffff
#define R128_MAX_VB_VERTS (0xffff)
#define R128_PCIGART_TABLE_ORDER 3
#define R128_PCIGART_TABLE_PAGES (1 << 3)
#define R128_MAX_PCIGART_PAGES 8192 /* 32 MB aperture */
#define R128_BASE(reg) ((u32)(dev_priv->mmio->handle))
#define R128_ADDR(reg) (R128_BASE(reg) + reg)

View file

@ -25,36 +25,28 @@
*
* Authors:
* Gareth Hughes <gareth@valinux.com>
*
*/
#define __NO_VERSION__
#include "drmP.h"
#include "r128_drv.h"
#include <linux/interrupt.h> /* For task queue support */
#include <linux/delay.h>
static unsigned long r128_alloc_pages( void )
static unsigned long r128_alloc_pcigart_table( void )
{
unsigned long address;
unsigned long addr_end;
struct page *page;
int i;
DRM_DEBUG( "%s\n", __FUNCTION__ );
address = __get_free_pages( GFP_KERNEL, 3 );
address = __get_free_pages( GFP_KERNEL, R128_PCIGART_TABLE_ORDER );
if ( address == 0UL ) {
return 0;
}
addr_end = address + ((PAGE_SIZE * (1 << 3)) - 1);
for (page = virt_to_page(address);
page <= virt_to_page(addr_end);
page++) {
page = virt_to_page( address );
for ( i = 0 ; i <= R128_PCIGART_TABLE_PAGES ; i++, page++ ) {
atomic_inc( &page->count );
SetPageReserved( page );
}
@ -63,24 +55,22 @@ static unsigned long r128_alloc_pages( void )
return address;
}
static void r128_free_pages( unsigned long address )
static void r128_free_pcigart_table( unsigned long address )
{
unsigned long addr_end;
struct page *page;
int i;
DRM_DEBUG( "%s\n", __FUNCTION__ );
if ( !address ) return;
addr_end = address + ((PAGE_SIZE * (1 << 3)) - 1);
page = virt_to_page( address );
for (page = virt_to_page(address);
page <= virt_to_page(addr_end);
page++) {
for ( i = 0 ; i <= R128_PCIGART_TABLE_PAGES ; i++, page++ ) {
atomic_dec( &page->count );
ClearPageReserved( page );
}
free_pages( address , 3 );
free_pages( address, R128_PCIGART_TABLE_ORDER );
}
int r128_pcigart_init( drm_device_t *dev )
@ -89,50 +79,36 @@ int r128_pcigart_init( drm_device_t *dev )
drm_sg_mem_t *entry = dev->sg;
unsigned long address;
unsigned long pages;
unsigned long *pci_gart;
u32 *pci_gart;
int i;
DRM_DEBUG( "%s\n", __FUNCTION__ );
#if 0
dev_priv->phys_pci_gart_page = 0;
dev_priv->pci_gart_page = NULL;
return 0;
#endif
if ( !entry ) {
DRM_ERROR( "no scatter/gather memory!\n" );
return -EINVAL;
}
/* 32 MB aperture is the largest size */
pages = ( entry->pages <= 8192 )
? entry->pages : 8192;
address = r128_alloc_pages();
address = r128_alloc_pcigart_table();
if ( !address ) {
DRM_ERROR( "cannot allocate PCI GART page!\n" );
return -ENOMEM;
}
dev_priv->phys_pci_gart_page = address;
dev_priv->pci_gart_page = (unsigned long *)address;
dev_priv->phys_pci_gart = address;
DRM_DEBUG( "%s: phys=0x%08lx virt=%p\n",
__FUNCTION__, dev_priv->phys_pci_gart_page,
dev_priv->pci_gart_page );
pci_gart = (u32 *)dev_priv->phys_pci_gart;
pci_gart = (unsigned long *)dev_priv->pci_gart_page;
pages = ( entry->pages <= R128_MAX_PCIGART_PAGES )
? entry->pages : R128_MAX_PCIGART_PAGES;
memset( pci_gart, 0, R128_MAX_PCIGART_PAGES * sizeof(u32) );
for ( i = 0; i < 8192 ; i++) pci_gart[i] = 0;
for ( i = 0 ; i < pages ; i++ ) {
pci_gart[i] = virt_to_bus( entry->pagelist[i]->virtual );
pci_gart[i] = (u32) virt_to_bus( entry->pagelist[i]->virtual );
}
DRM_DEBUG( "%s: writing PCI_GART_PAGE...\n", __FUNCTION__ );
R128_WRITE( R128_PCI_GART_PAGE, virt_to_bus((void *)address) );
R128_WRITE( R128_PCI_GART_PAGE, virt_to_bus( (void *)address ) );
DRM_DEBUG( "%s: writing PCI_GART_PAGE... done.\n", __FUNCTION__ );
#if __i386__
@ -149,10 +125,9 @@ int r128_pcigart_cleanup( drm_device_t *dev )
drm_r128_private_t *dev_priv = dev->dev_private;
DRM_DEBUG( "%s\n", __FUNCTION__ );
if ( dev_priv->phys_pci_gart_page ) {
r128_free_pages( dev_priv->phys_pci_gart_page );
if ( dev_priv->phys_pci_gart ) {
r128_free_pcigart_table( dev_priv->phys_pci_gart );
}
return 0;
}

View file

@ -616,9 +616,6 @@ static void r128_cce_dispatch_vertex( drm_device_t *dev,
drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
int format = sarea_priv->vc_format;
int offset = buf->bus_address;
/*
int offset = dev_priv->buffers->offset + buf->offset - dev->agp->base;
*/
int size = buf->used;
int prim = buf_priv->prim;
int i = 0;
@ -685,9 +682,6 @@ static void r128_cce_dispatch_vertex( drm_device_t *dev,
sarea_priv->nbox = 0;
}
static void r128_cce_dispatch_indirect( drm_device_t *dev,
drm_buf_t *buf,
int start, int end )
@ -752,12 +746,11 @@ static void r128_cce_dispatch_indices( drm_device_t *dev,
int start, int end,
int count )
{
drm_device_dma_t *dma = dev->dma;
drm_r128_private_t *dev_priv = dev->dev_private;
drm_r128_buf_priv_t *buf_priv = buf->dev_private;
drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
int format = sarea_priv->vc_format;
int offset;
int offset = dev_priv->buffers->offset - dev_priv->cce_buffers_offset;
int prim = buf_priv->prim;
u32 *data;
int dwords;
@ -765,15 +758,6 @@ static void r128_cce_dispatch_indices( drm_device_t *dev,
RING_LOCALS;
DRM_DEBUG( "indices: s=%d e=%d c=%d\n", start, end, count );
if(dma->flags == _DRM_DMA_USE_SG)
offset = dev_priv->buffers->offset - dev->sg->handle;
else
#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
offset = dev_priv->buffers->offset - dev->agp->base;
#else
printk("WARNING: trying to use AGP without kernel support!\n");
#endif
r128_update_ring_snapshot( dev_priv );
if ( 0 )
@ -1436,10 +1420,8 @@ int r128_cce_vertex( struct inode *inode, struct file *filp,
DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
return -EINVAL;
}
if ( !dev_priv ) {
DRM_ERROR( "%s called with a PCI card\n", __FUNCTION__ );
if ( !dev_priv )
return -EINVAL;
}
if ( copy_from_user( &vertex, (drm_r128_vertex_t *)arg,
sizeof(vertex) ) )
@ -1501,10 +1483,8 @@ int r128_cce_indices( struct inode *inode, struct file *filp,
DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
return -EINVAL;
}
if ( !dev_priv ) {
DRM_ERROR( "%s called with a PCI card\n", __FUNCTION__ );
if ( !dev_priv )
return -EINVAL;
}
if ( copy_from_user( &elts, (drm_r128_indices_t *)arg,
sizeof(elts) ) )

View file

@ -24,24 +24,25 @@
* DEALINGS IN THE SOFTWARE.
*
* Authors:
* Gareth Hughes <gareth@valinux.com>
*
* Gareth Hughes <gareth@valinux.com>
*/
#define __NO_VERSION__
#include <linux/config.h>
#include <linux/vmalloc.h>
#include "drmP.h"
#include <linux/wrapper.h>
#define DEBUG_SCATTER 0
void drm_sg_cleanup( drm_sg_mem_t *entry )
{
struct page *page;
int i;
for ( i = 0 ; i < entry->pages ; i++ ) {
ClearPageReserved( entry->pagelist[i] );
page = entry->pagelist[i];
if ( page )
ClearPageReserved( page );
}
vfree( entry->virtual );
@ -54,15 +55,6 @@ void drm_sg_cleanup( drm_sg_mem_t *entry )
DRM_MEM_SGLISTS );
}
static inline long usec( void )
{
struct timeval tv;
do_gettimeofday( &tv );
return (tv.tv_sec & 0x7ff) * 1000000 + tv.tv_usec;
}
int drm_sg_alloc( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
@ -77,7 +69,8 @@ int drm_sg_alloc( struct inode *inode, struct file *filp,
DRM_DEBUG( "%s\n", __FUNCTION__ );
if ( dev->sg ) return -EINVAL;
if ( dev->sg )
return -EINVAL;
if ( copy_from_user( &request,
(drm_scatter_gather_t *)arg,
@ -85,7 +78,8 @@ int drm_sg_alloc( struct inode *inode, struct file *filp,
return -EFAULT;
entry = drm_alloc( sizeof(*entry), DRM_MEM_SGLISTS );
if ( !entry ) return -ENOMEM;
if ( !entry )
return -ENOMEM;
memset( entry, 0, sizeof(*entry) );
@ -100,11 +94,7 @@ int drm_sg_alloc( struct inode *inode, struct file *filp,
return -ENOMEM;
}
/* FIXME: We should really have a kernel call for this...
*/
entry->virtual = __vmalloc( (pages << PAGE_SHIFT),
GFP_KERNEL,
PAGE_KERNEL);
entry->virtual = vmalloc_32( pages << PAGE_SHIFT );
if ( !entry->virtual ) {
drm_free( entry->pagelist,
entry->pages * sizeof(*entry->pagelist),
@ -127,30 +117,20 @@ int drm_sg_alloc( struct inode *inode, struct file *filp,
for ( i = entry->handle, j = 0 ; j < pages ; i += PAGE_SIZE, j++ ) {
pgd = pgd_offset_k( i );
if ( !pgd_present( *pgd ) )
goto failed;
if ( pgd_present( *pgd ) && ( pmd = pmd_offset( pgd, i ) )
&& pmd_present( *pmd ) && ( pte = pte_offset( pmd, i ) )
&& pte_present( *pte ) )
entry->pagelist[j] = pte_page( *pte );
else
{
vfree( entry->virtual );
drm_free( entry->pagelist,
entry->pages * sizeof(*entry->pagelist),
DRM_MEM_PAGES );
drm_free( entry,
sizeof(*entry),
DRM_MEM_SGLISTS );
return -ENOMEM;
}
pmd = pmd_offset( pgd, i );
if ( !pmd_present( *pmd ) )
goto failed;
pte = pte_offset( pmd, i );
if ( !pte_present( *pte ) )
goto failed;
entry->pagelist[j] = pte_page( *pte );
SetPageReserved( entry->pagelist[j] );
if ( j < 16 ) {
DRM_DEBUG("0x%08lx (page %lu) => 0x%08lx\n",
i, j,
(unsigned long)entry->pagelist[j]->virtual);
}
}
request.handle = entry->handle;
@ -165,7 +145,7 @@ int drm_sg_alloc( struct inode *inode, struct file *filp,
dev->sg = entry;
#if DEBUG_SCATTER
/* Verify that each page points to its virtual address, and vice
/* Verify that each page points to its virtual address, and vice
* versa.
*/
{
@ -178,7 +158,7 @@ int drm_sg_alloc( struct inode *inode, struct file *filp,
for(j = 0; j < PAGE_SIZE / sizeof(unsigned long); j++, tmp++) {
*tmp = 0xcafebabe;
}
tmp = (unsigned long *)((u8 *)entry->virtual +
tmp = (unsigned long *)((u8 *)entry->virtual +
(PAGE_SIZE * i));
for(j = 0; j < PAGE_SIZE / sizeof(unsigned long); j++, tmp++) {
if(*tmp != 0xcafebabe && error == 0) {
@ -197,6 +177,10 @@ int drm_sg_alloc( struct inode *inode, struct file *filp,
#endif
return 0;
failed:
drm_sg_cleanup( entry );
return -ENOMEM;
}
int drm_sg_free( struct inode *inode, struct file *filp,
@ -215,7 +199,8 @@ int drm_sg_free( struct inode *inode, struct file *filp,
entry = dev->sg;
dev->sg = NULL;
if ( !entry || entry->handle != request.handle ) return -EINVAL;
if ( !entry || entry->handle != request.handle )
return -EINVAL;
DRM_DEBUG( "sg free virtual = %p\n", entry->virtual );

View file

@ -11,11 +11,11 @@
* 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
@ -23,7 +23,7 @@
* 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.
*
*
* Authors:
* Rickard E. (Rik) Faith <faith@valinux.com>
*
@ -213,7 +213,6 @@ struct page *drm_vm_sg_nopage(struct vm_area_struct *vma,
page = entry->pagelist[page_offset];
atomic_inc(&page->count); /* Dec. by kernel */
#if LINUX_VERSION_CODE < 0x020317
return (unsigned long)virt_to_phys(page->virtual);
#else
@ -289,7 +288,7 @@ int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
drm_device_t *dev;
drm_device_dma_t *dma;
unsigned long length = vma->vm_end - vma->vm_start;
lock_kernel();
dev = priv->dev;
dma = dev->dma;
@ -305,7 +304,7 @@ int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
vma->vm_ops = &drm_vm_dma_ops;
vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */
#if LINUX_VERSION_CODE < 0x020203 /* KERNEL_VERSION(2,2,3) */
/* In Linux 2.2.3 and above, this is
handled in do_mmap() in mm/mmap.c. */
@ -322,7 +321,7 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
drm_device_t *dev = priv->dev;
drm_map_t *map = NULL;
int i;
DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n",
vma->vm_start, vma->vm_end, VM_OFFSET(vma));
@ -339,14 +338,14 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
map = dev->maplist[i];
if (map->offset == VM_OFFSET(vma)) break;
}
if (i >= dev->map_count) return -EINVAL;
if (!map || ((map->flags&_DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN)))
return -EPERM;
/* Check for valid size. */
if (map->size != vma->vm_end - vma->vm_start) return -EINVAL;
if (!capable(CAP_SYS_ADMIN) && (map->flags & _DRM_READ_ONLY)) {
vma->vm_flags &= VM_MAYWRITE;
#if defined(__i386__)
@ -360,12 +359,6 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
#endif
}
if (map->type == _DRM_SCATTER_GATHER) {
DRM_DEBUG("%s: scatter/gather\n", __FUNCTION__);
DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n",
vma->vm_start, vma->vm_end, VM_OFFSET(vma));
}
switch (map->type) {
case _DRM_FRAME_BUFFER:
case _DRM_REGISTERS:
@ -377,10 +370,12 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
pgprot_val(vma->vm_page_prot) &= ~_PAGE_PWT;
}
#elif defined(__powerpc__)
pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE|_PAGE_GUARDED;
pgprot_val(vma->vm_page_prot) |=
_PAGE_NO_CACHE | _PAGE_GUARDED;
#elif defined(__ia64__)
if (map->type != _DRM_AGP)
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
vma->vm_page_prot =
pgprot_writecombine(vma->vm_page_prot);
#endif
vma->vm_flags |= VM_IO; /* not in core dump */
}
@ -432,9 +427,5 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
#endif
vma->vm_file = filp; /* Needed for drm_vm_open() */
drm_vm_open(vma);
if(map->type == _DRM_SCATTER_GATHER) {
DRM_DEBUG("%s: scatter/gather done.\n", __FUNCTION__);
}
return 0;
}