diff options
-rw-r--r-- | linux-core/r128_drv.c | 4 | ||||
-rw-r--r-- | linux/Makefile.linux | 6 | ||||
-rw-r--r-- | linux/bufs.c | 41 | ||||
-rw-r--r-- | linux/r128_bufs.c | 10 | ||||
-rw-r--r-- | linux/r128_cce.c | 58 | ||||
-rw-r--r-- | linux/r128_drv.c | 4 | ||||
-rw-r--r-- | linux/r128_drv.h | 11 | ||||
-rw-r--r-- | linux/r128_pcigart.c | 73 | ||||
-rw-r--r-- | linux/r128_state.c | 26 | ||||
-rw-r--r-- | linux/scatter.c | 73 | ||||
-rw-r--r-- | linux/vm.c | 33 |
11 files changed, 136 insertions, 203 deletions
diff --git a/linux-core/r128_drv.c b/linux-core/r128_drv.c index 977be8ea..ddc1103f 100644 --- a/linux-core/r128_drv.c +++ b/linux-core/r128_drv.c @@ -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; } diff --git a/linux/Makefile.linux b/linux/Makefile.linux index ecbe5aca..c312ba85 100644 --- a/linux/Makefile.linux +++ b/linux/Makefile.linux @@ -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 diff --git a/linux/bufs.c b/linux/bufs.c index 127ef142..3d13d899 100644 --- a/linux/bufs.c +++ b/linux/bufs.c @@ -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); diff --git a/linux/r128_bufs.c b/linux/r128_bufs.c index 2730e07b..4d5004fa 100644 --- a/linux/r128_bufs.c +++ b/linux/r128_bufs.c @@ -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, diff --git a/linux/r128_cce.c b/linux/r128_cce.c index 144f2ab9..ca1991f2 100644 --- a/linux/r128_cce.c +++ b/linux/r128_cce.c @@ -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; diff --git a/linux/r128_drv.c b/linux/r128_drv.c index 977be8ea..ddc1103f 100644 --- a/linux/r128_drv.c +++ b/linux/r128_drv.c @@ -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; } diff --git a/linux/r128_drv.h b/linux/r128_drv.h index 6b6a04c2..3c02dbc5 100644 --- a/linux/r128_drv.h +++ b/linux/r128_drv.h @@ -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) diff --git a/linux/r128_pcigart.c b/linux/r128_pcigart.c index d0f05cce..ff32f1dc 100644 --- a/linux/r128_pcigart.c +++ b/linux/r128_pcigart.c @@ -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; } - diff --git a/linux/r128_state.c b/linux/r128_state.c index 29750456..f6ff3838 100644 --- a/linux/r128_state.c +++ b/linux/r128_state.c @@ -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) ) ) diff --git a/linux/scatter.c b/linux/scatter.c index 8bd4bd82..36066e64 100644 --- a/linux/scatter.c +++ b/linux/scatter.c @@ -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; - SetPageReserved( entry->pagelist[j] ); + pte = pte_offset( pmd, i ); + if ( !pte_present( *pte ) ) + goto failed; - if ( j < 16 ) { - DRM_DEBUG("0x%08lx (page %lu) => 0x%08lx\n", - i, j, - (unsigned long)entry->pagelist[j]->virtual); - } + entry->pagelist[j] = pte_page( *pte ); + + SetPageReserved( entry->pagelist[j] ); } 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 ); @@ -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; } |