2005-09-25 14:28:13 +10:00
/**
* \ file drm_memory . c
2005-04-16 15:20:36 -07:00
* Memory management wrappers for DRM
*
* \ author Rickard E . ( Rik ) Faith < faith @ valinux . com >
* \ author Gareth Hughes < gareth @ valinux . com >
*/
2005-09-25 14:28:13 +10:00
/*
2005-04-16 15:20:36 -07:00
* Created : Thu Feb 4 14 : 00 : 34 1999 by faith @ valinux . com
*
* Copyright 1999 Precision Insight , Inc . , Cedar Park , Texas .
* Copyright 2000 VA Linux Systems , Inc . , Sunnyvale , California .
* 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
* VA LINUX SYSTEMS AND / OR ITS SUPPLIERS 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 <linux/highmem.h>
# include "drmP.h"
# ifdef DEBUG_MEMORY
# include "drm_memory_debug.h"
# else
/** No-op. */
void drm_mem_init ( void )
{
}
/**
* Called when " /proc/dri/%dev%/mem " is read .
2005-09-25 14:28:13 +10:00
*
2005-04-16 15:20:36 -07:00
* \ param buf output buffer .
* \ param start start of output data .
* \ param offset requested start offset .
* \ param len requested number of bytes .
* \ param eof whether there is no more data to return .
* \ param data private data .
* \ return number of written bytes .
*
2005-09-25 14:28:13 +10:00
* No - op .
2005-04-16 15:20:36 -07:00
*/
int drm_mem_info ( char * buf , char * * start , off_t offset ,
2005-09-25 14:28:13 +10:00
int len , int * eof , void * data )
2005-04-16 15:20:36 -07:00
{
return 0 ;
}
/** Wrapper around kmalloc() and kfree() */
void * drm_realloc ( void * oldpt , size_t oldsize , size_t size , int area )
{
void * pt ;
2005-09-25 14:28:13 +10:00
if ( ! ( pt = kmalloc ( size , GFP_KERNEL ) ) )
return NULL ;
2005-04-16 15:20:36 -07:00
if ( oldpt & & oldsize ) {
memcpy ( pt , oldpt , oldsize ) ;
kfree ( oldpt ) ;
}
return pt ;
}
# if __OS_HAS_AGP
2006-04-10 23:18:27 -07:00
static void * agp_remap ( unsigned long offset , unsigned long size ,
2007-07-11 15:53:27 +10:00
struct drm_device * dev )
2006-04-07 16:55:43 +10:00
{
unsigned long * phys_addr_map , i , num_pages =
PAGE_ALIGN ( size ) / PAGE_SIZE ;
struct drm_agp_mem * agpmem ;
struct page * * page_map ;
void * addr ;
size = PAGE_ALIGN ( size ) ;
# ifdef __alpha__
offset - = dev - > hose - > mem_space - > start ;
# endif
2007-05-26 05:01:51 +10:00
list_for_each_entry ( agpmem , & dev - > agp - > memory , head )
2006-04-07 16:55:43 +10:00
if ( agpmem - > bound < = offset
& & ( agpmem - > bound + ( agpmem - > pages < < PAGE_SHIFT ) ) > =
( offset + size ) )
break ;
if ( ! agpmem )
return NULL ;
/*
* OK , we ' re mapping AGP space on a chipset / platform on which memory accesses by
* the CPU do not get remapped by the GART . We fix this by using the kernel ' s
* page - table instead ( that ' s probably faster anyhow . . . ) .
*/
/* note: use vmalloc() because num_pages could be large... */
page_map = vmalloc ( num_pages * sizeof ( struct page * ) ) ;
if ( ! page_map )
return NULL ;
phys_addr_map =
agpmem - > memory - > memory + ( offset - agpmem - > bound ) / PAGE_SIZE ;
for ( i = 0 ; i < num_pages ; + + i )
page_map [ i ] = pfn_to_page ( phys_addr_map [ i ] > > PAGE_SHIFT ) ;
addr = vmap ( page_map , num_pages , VM_IOREMAP , PAGE_AGP ) ;
vfree ( page_map ) ;
return addr ;
}
2005-04-16 15:20:36 -07:00
/** Wrapper around agp_allocate_memory() */
2007-07-11 15:53:27 +10:00
DRM_AGP_MEM * drm_alloc_agp ( struct drm_device * dev , int pages , u32 type )
2005-04-16 15:20:36 -07:00
{
2005-07-10 18:17:42 +10:00
return drm_agp_allocate_memory ( dev - > agp - > bridge , pages , type ) ;
2005-04-16 15:20:36 -07:00
}
2005-09-25 14:28:13 +10:00
2005-04-16 15:20:36 -07:00
/** Wrapper around agp_free_memory() */
2005-09-25 14:28:13 +10:00
int drm_free_agp ( DRM_AGP_MEM * handle , int pages )
2005-04-16 15:20:36 -07:00
{
return drm_agp_free_memory ( handle ) ? 0 : - EINVAL ;
}
2008-07-30 12:06:12 -07:00
EXPORT_SYMBOL ( drm_free_agp ) ;
2005-09-25 14:28:13 +10:00
2005-04-16 15:20:36 -07:00
/** Wrapper around agp_bind_memory() */
2005-09-25 14:28:13 +10:00
int drm_bind_agp ( DRM_AGP_MEM * handle , unsigned int start )
2005-04-16 15:20:36 -07:00
{
return drm_agp_bind_memory ( handle , start ) ;
}
2005-09-25 14:28:13 +10:00
2005-04-16 15:20:36 -07:00
/** Wrapper around agp_unbind_memory() */
2005-09-25 14:28:13 +10:00
int drm_unbind_agp ( DRM_AGP_MEM * handle )
2005-04-16 15:20:36 -07:00
{
return drm_agp_unbind_memory ( handle ) ;
}
2008-07-30 12:06:12 -07:00
EXPORT_SYMBOL ( drm_unbind_agp ) ;
2006-04-10 23:18:27 -07:00
# else /* __OS_HAS_AGP */
static inline void * agp_remap ( unsigned long offset , unsigned long size ,
2007-07-11 15:53:27 +10:00
struct drm_device * dev )
2006-04-10 23:18:27 -07:00
{
return NULL ;
}
2005-09-25 14:28:13 +10:00
# endif /* agp */
2006-04-07 16:55:43 +10:00
2007-01-08 21:56:59 +11:00
# endif /* debug_memory */
2006-04-07 16:55:43 +10:00
2009-02-02 16:55:46 +11:00
void drm_core_ioremap ( struct drm_local_map * map , struct drm_device * dev )
2006-04-07 16:55:43 +10:00
{
2007-01-08 21:56:59 +11:00
if ( drm_core_has_AGP ( dev ) & &
dev - > agp & & dev - > agp - > cant_use_aperture & & map - > type = = _DRM_AGP )
map - > handle = agp_remap ( map - > offset , map - > size , dev ) ;
else
map - > handle = ioremap ( map - > offset , map - > size ) ;
2006-04-07 16:55:43 +10:00
}
2007-01-08 21:56:59 +11:00
EXPORT_SYMBOL ( drm_core_ioremap ) ;
2006-04-07 16:55:43 +10:00
2009-02-02 16:55:46 +11:00
void drm_core_ioremap_wc ( struct drm_local_map * map , struct drm_device * dev )
2008-07-15 15:48:05 +10:00
{
2009-02-07 11:15:41 +10:00
if ( drm_core_has_AGP ( dev ) & &
dev - > agp & & dev - > agp - > cant_use_aperture & & map - > type = = _DRM_AGP )
map - > handle = agp_remap ( map - > offset , map - > size , dev ) ;
else
map - > handle = ioremap_wc ( map - > offset , map - > size ) ;
2008-07-15 15:48:05 +10:00
}
EXPORT_SYMBOL ( drm_core_ioremap_wc ) ;
2009-02-07 11:15:41 +10:00
2009-02-02 16:55:46 +11:00
void drm_core_ioremapfree ( struct drm_local_map * map , struct drm_device * dev )
2006-04-07 16:55:43 +10:00
{
2007-01-08 21:56:59 +11:00
if ( ! map - > handle | | ! map - > size )
return ;
if ( drm_core_has_AGP ( dev ) & &
dev - > agp & & dev - > agp - > cant_use_aperture & & map - > type = = _DRM_AGP )
vunmap ( map - > handle ) ;
else
iounmap ( map - > handle ) ;
2006-04-07 16:55:43 +10:00
}
2007-01-08 21:56:59 +11:00
EXPORT_SYMBOL ( drm_core_ioremapfree ) ;