diff options
Diffstat (limited to 'linux-core')
| -rw-r--r-- | linux-core/xgi_drv.c | 46 | ||||
| -rw-r--r-- | linux-core/xgi_drv.h | 34 | ||||
| -rw-r--r-- | linux-core/xgi_fb.c | 281 | ||||
| -rw-r--r-- | linux-core/xgi_pcie.c | 6 | 
4 files changed, 54 insertions, 313 deletions
| diff --git a/linux-core/xgi_drv.c b/linux-core/xgi_drv.c index 997051fb..b0f84c81 100644 --- a/linux-core/xgi_drv.c +++ b/linux-core/xgi_drv.c @@ -225,7 +225,7 @@ int xgi_bootstrap(struct drm_device * dev, void * data,  	/* Init the resource manager */ -	if (!info->fb_heap.initialized) { +	if (!info->fb_heap_initialized) {  		err = xgi_fb_heap_init(info);  		if (err) {  			DRM_ERROR("Unable to initialize FB heap.\n"); @@ -237,7 +237,7 @@ int xgi_bootstrap(struct drm_device * dev, void * data,  	info->pcie.size = bs->gart.size;  	/* Init the resource manager */ -	if (!info->pcie_heap.initialized) { +	if (!info->pcie_heap_initialized) {  		err = xgi_pcie_heap_init(info);  		if (err) {  			DRM_ERROR("Unable to initialize GART heap.\n"); @@ -296,13 +296,13 @@ void xgi_driver_lastclose(struct drm_device * dev)  		info->mmio_map = NULL;  		info->fb_map = NULL; -		if (info->fb_heap.initialized) { -			xgi_mem_heap_cleanup(&info->fb_heap); +		if (info->pcie_heap_initialized) { +			xgi_pcie_lut_cleanup(info);  		} -		if (info->pcie_heap.initialized) { -			xgi_mem_heap_cleanup(&info->pcie_heap); -			xgi_pcie_lut_cleanup(info); +		if (info->fb_heap_initialized +		    || info->pcie_heap_initialized) { +			drm_sman_cleanup(&info->sman);  		}  	}  } @@ -314,12 +314,16 @@ void xgi_reclaim_buffers_locked(struct drm_device * dev,  	struct xgi_info * info = dev->dev_private;  	mutex_lock(&info->dev->struct_mutex); +	if (drm_sman_owner_clean(&info->sman, (unsigned long) filp)) { +		mutex_unlock(&info->dev->struct_mutex); +		return; +	} +  	if (dev->driver->dma_quiescent) {  		dev->driver->dma_quiescent(dev);  	} -	xgi_free_all(info, &info->pcie_heap, filp); -	xgi_free_all(info, &info->fb_heap, filp); +	drm_sman_owner_cleanup(&info->sman, (unsigned long) filp);  	mutex_unlock(&info->dev->struct_mutex);  	return;  } @@ -357,6 +361,7 @@ void xgi_kern_isr_bh(struct drm_device *dev)  int xgi_driver_load(struct drm_device *dev, unsigned long flags)  {  	struct xgi_info *info = drm_alloc(sizeof(*info), DRM_MEM_DRIVER); +	int err;  	if (!info)  		return -ENOMEM; @@ -375,7 +380,8 @@ int xgi_driver_load(struct drm_device *dev, unsigned long flags)  	if ((info->mmio.base == 0) || (info->mmio.size == 0)) {  		DRM_ERROR("mmio appears to be wrong: 0x%lx 0x%x\n",  			  (unsigned long) info->mmio.base, info->mmio.size); -		return -EINVAL; +		err = -EINVAL; +		goto fail;  	} @@ -386,28 +392,24 @@ int xgi_driver_load(struct drm_device *dev, unsigned long flags)  		 (unsigned long) info->fb.base, info->fb.size); -	xgi_mem_block_cache = kmem_cache_create("xgi_mem_block", -						sizeof(struct xgi_mem_block), -						0, -						SLAB_HWCACHE_ALIGN, -						NULL, NULL); -	if (xgi_mem_block_cache == NULL) { -		return -ENOMEM; +	err = drm_sman_init(&info->sman, 2, 12, 8); +	if (err) { +		goto fail;  	}  	return 0; +	 +fail: +	drm_free(info, sizeof(*info), DRM_MEM_DRIVER); +	return err;  }  int xgi_driver_unload(struct drm_device *dev)  {  	struct xgi_info * info = dev->dev_private; -	if (xgi_mem_block_cache) { -		kmem_cache_destroy(xgi_mem_block_cache); -		xgi_mem_block_cache = NULL; -	} - +	drm_sman_takedown(&info->sman);  	drm_free(info, sizeof(*info), DRM_MEM_DRIVER);  	dev->dev_private = NULL; diff --git a/linux-core/xgi_drv.h b/linux-core/xgi_drv.h index e56d00bb..6b209aa4 100644 --- a/linux-core/xgi_drv.h +++ b/linux-core/xgi_drv.h @@ -29,6 +29,7 @@  #include "drmP.h"  #include "drm.h" +#include "drm_sman.h"  #define DRIVER_AUTHOR		"Andrea Zhang <andrea_zhang@macrosynergy.com>" @@ -38,7 +39,7 @@  #define DRIVER_MAJOR		0  #define DRIVER_MINOR		11 -#define DRIVER_PATCHLEVEL	0 +#define DRIVER_PATCHLEVEL	1  #include "xgi_cmdlist.h"  #include "xgi_drm.h" @@ -48,22 +49,6 @@ struct xgi_aperture {  	unsigned int size;  }; -struct xgi_mem_block { -	struct list_head list; -	unsigned long offset; -	unsigned long size; -	struct drm_file * filp; -}; - -struct xgi_mem_heap { -	struct list_head free_list; -	struct list_head used_list; -	struct list_head sort_list; -	unsigned long max_freesize; - -	bool initialized; -}; -  struct xgi_info {  	struct drm_device *dev; @@ -82,19 +67,13 @@ struct xgi_info {  	struct drm_dma_handle *lut_handle;  	unsigned int lutPageSize; -	struct xgi_mem_heap fb_heap; -	struct xgi_mem_heap pcie_heap; +	struct drm_sman sman; +	bool fb_heap_initialized; +	bool pcie_heap_initialized;  	struct xgi_cmdring_info cmdring;  }; -extern struct kmem_cache *xgi_mem_block_cache; -extern int xgi_mem_free(struct xgi_mem_heap * heap, unsigned long offset, -	struct drm_file * filp); -extern int xgi_mem_heap_init(struct xgi_mem_heap * heap, unsigned int start, -	unsigned int end); -extern void xgi_mem_heap_cleanup(struct xgi_mem_heap * heap); -  extern int xgi_fb_heap_init(struct xgi_info * info);  extern int xgi_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc, @@ -108,9 +87,6 @@ extern void xgi_pcie_lut_cleanup(struct xgi_info * info);  extern void *xgi_find_pcie_virt(struct xgi_info * info, u32 address); -extern void xgi_free_all(struct xgi_info *, struct xgi_mem_heap *, -	struct drm_file *); -  extern int xgi_alloc_ioctl(struct drm_device * dev, void * data,  	struct drm_file * filp);  extern int xgi_free_ioctl(struct drm_device * dev, void * data, diff --git a/linux-core/xgi_fb.c b/linux-core/xgi_fb.c index d0182831..40f39fbc 100644 --- a/linux-core/xgi_fb.c +++ b/linux-core/xgi_fb.c @@ -28,225 +28,10 @@  #define XGI_FB_HEAP_START 0x1000000 -struct kmem_cache *xgi_mem_block_cache = NULL; - -static struct xgi_mem_block *xgi_mem_new_node(void); - - -int xgi_mem_heap_init(struct xgi_mem_heap *heap, unsigned int start, -		      unsigned int end) -{ -	struct xgi_mem_block *block; - -	INIT_LIST_HEAD(&heap->free_list); -	INIT_LIST_HEAD(&heap->used_list); -	INIT_LIST_HEAD(&heap->sort_list); -	heap->initialized = TRUE; - -	block = kmem_cache_alloc(xgi_mem_block_cache, GFP_KERNEL); -	if (!block) { -		return -ENOMEM; -	} - -	block->offset = start; -	block->size = end - start; - -	list_add(&block->list, &heap->free_list); - -	heap->max_freesize = end - start; - -	return 0; -} - - -void xgi_mem_heap_cleanup(struct xgi_mem_heap * heap) -{ -	struct list_head *free_list; -	struct xgi_mem_block *block; -	struct xgi_mem_block *next; -	int i; - -	free_list = &heap->free_list; -	for (i = 0; i < 3; i++, free_list++) { -		list_for_each_entry_safe(block, next, free_list, list) { -			DRM_INFO -				("No. %d block->offset: 0x%lx block->size: 0x%lx \n", -				 i, block->offset, block->size); -			kmem_cache_free(xgi_mem_block_cache, block); -			block = NULL; -		} -	} -	 -	heap->initialized = 0; -} - - -struct xgi_mem_block *xgi_mem_new_node(void) -{ -	struct xgi_mem_block *block = -		kmem_cache_alloc(xgi_mem_block_cache, GFP_KERNEL); - -	if (!block) { -		DRM_ERROR("kmem_cache_alloc failed\n"); -		return NULL; -	} - -	block->offset = 0; -	block->size = 0; -	block->filp = (struct drm_file *) -1; - -	return block; -} - - -static struct xgi_mem_block *xgi_mem_alloc(struct xgi_mem_heap * heap, -					   unsigned long originalSize) -{ -	struct xgi_mem_block *block, *free_block, *used_block; -	unsigned long size = (originalSize + PAGE_SIZE - 1) & PAGE_MASK; - - -	DRM_INFO("Original 0x%lx bytes requested, really 0x%lx allocated\n", -		 originalSize, size); - -	if (size == 0) { -		DRM_ERROR("size == 0\n"); -		return (NULL); -	} -	DRM_INFO("max_freesize: 0x%lx \n", heap->max_freesize); -	if (size > heap->max_freesize) { -		DRM_ERROR -		    ("size: 0x%lx is bigger than frame buffer total free size: 0x%lx !\n", -		     size, heap->max_freesize); -		return (NULL); -	} - -	list_for_each_entry(block, &heap->free_list, list) { -		DRM_INFO("block: 0x%px \n", block); -		if (size <= block->size) { -			break; -		} -	} - -	if (&block->list == &heap->free_list) { -		DRM_ERROR -		    ("Can't allocate %ldk size from frame buffer memory !\n", -		     size / 1024); -		return (NULL); -	} - -	free_block = block; -	DRM_INFO("alloc size: 0x%lx from offset: 0x%lx size: 0x%lx \n", -		 size, free_block->offset, free_block->size); - -	if (size == free_block->size) { -		used_block = free_block; -		DRM_INFO("size == free_block->size: free_block = 0x%p\n", -			 free_block); -		list_del(&free_block->list); -	} else { -		used_block = xgi_mem_new_node(); - -		if (used_block == NULL) -			return (NULL); - -		if (used_block == free_block) { -			DRM_ERROR("used_block == free_block = 0x%p\n", -				  used_block); -		} - -		used_block->offset = free_block->offset; -		used_block->size = size; - -		free_block->offset += size; -		free_block->size -= size; -	} - -	heap->max_freesize -= size; - -	list_add(&used_block->list, &heap->used_list); - -	return (used_block); -} - -int xgi_mem_free(struct xgi_mem_heap * heap, unsigned long offset, -		 struct drm_file * filp) -{ -	struct xgi_mem_block *used_block = NULL, *block; -	struct xgi_mem_block *prev, *next; - -	unsigned long upper; -	unsigned long lower; - -	list_for_each_entry(block, &heap->used_list, list) { -		if (block->offset == offset) { -			break; -		} -	} - -	if (&block->list == &heap->used_list) { -		DRM_ERROR("can't find block: 0x%lx to free!\n", offset); -		return -ENOENT; -	} - -	if (block->filp != filp) { -		return -EPERM; -	} - -	used_block = block; -	DRM_INFO("used_block: 0x%p, offset = 0x%lx, size = 0x%lx\n", -		 used_block, used_block->offset, used_block->size); - -	heap->max_freesize += used_block->size; - -	prev = next = NULL; -	upper = used_block->offset + used_block->size; -	lower = used_block->offset; - -	list_for_each_entry(block, &heap->free_list, list) { -		if (block->offset == upper) { -			next = block; -		} else if ((block->offset + block->size) == lower) { -			prev = block; -		} -	} - -	DRM_INFO("next = 0x%p, prev = 0x%p\n", next, prev); -	list_del(&used_block->list); - -	if (prev && next) { -		prev->size += (used_block->size + next->size); -		list_del(&next->list); -		DRM_INFO("free node 0x%p\n", next); -		kmem_cache_free(xgi_mem_block_cache, next); -		kmem_cache_free(xgi_mem_block_cache, used_block); -	} -	else if (prev) { -		prev->size += used_block->size; -		DRM_INFO("free node 0x%p\n", used_block); -		kmem_cache_free(xgi_mem_block_cache, used_block); -	} -	else if (next) { -		next->size += used_block->size; -		next->offset = used_block->offset; -		DRM_INFO("free node 0x%p\n", used_block); -		kmem_cache_free(xgi_mem_block_cache, used_block); -	} -	else { -		list_add(&used_block->list, &heap->free_list); -		DRM_INFO("Recycled free node %p, offset = 0x%lx, size = 0x%lx\n", -			 used_block, used_block->offset, used_block->size); -	} - -	return 0; -} - -  int xgi_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc,  	      struct drm_file * filp)  { -	struct xgi_mem_block *block; -	struct xgi_mem_heap *heap; +	struct drm_memblock_item *block;  	const char *const mem_name = (alloc->location == XGI_MEMLOC_LOCAL)   		? "on-card" : "GART"; @@ -258,17 +43,16 @@ int xgi_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc,  		return -EINVAL;  	} -	heap = (alloc->location == XGI_MEMLOC_LOCAL) -		? &info->fb_heap : &info->pcie_heap; -	 -	if (!heap->initialized) { +	if ((alloc->location == XGI_MEMLOC_LOCAL)  +	    ? !info->fb_heap_initialized : !info->pcie_heap_initialized) {  		DRM_ERROR("Attempt to allocate from uninitialized memory "  			  "pool (0x%08x).\n", alloc->location);  		return -EINVAL;  	}  	mutex_lock(&info->dev->struct_mutex); -	block = xgi_mem_alloc(heap, alloc->size); +	block = drm_sman_alloc(&info->sman, alloc->location, alloc->size, +			       0, (unsigned long) filp);  	mutex_unlock(&info->dev->struct_mutex);  	if (block == NULL) { @@ -276,18 +60,17 @@ int xgi_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc,  		DRM_ERROR("%s memory allocation failed\n", mem_name);  		return -ENOMEM;  	} else { -		DRM_DEBUG("%s memory allocation succeeded: 0x%p\n", -			  mem_name, (char *)block->offset); -		alloc->size = block->size; -		alloc->offset = block->offset; -		alloc->hw_addr = block->offset; -		alloc->index = alloc->offset | alloc->location; +		alloc->offset = (*block->mm->offset)(block->mm, +						     block->mm_info); +		alloc->hw_addr = alloc->offset; +		alloc->index = block->user_hash.key;  		if (alloc->location == XGI_MEMLOC_NON_LOCAL) {  			alloc->hw_addr += info->pcie.base;  		} -		block->filp = filp; +		DRM_DEBUG("%s memory allocation succeeded: 0x%x\n", +			  mem_name, alloc->offset);  	}  	return 0; @@ -307,13 +90,9 @@ int xgi_free(struct xgi_info * info, unsigned long index,  	     struct drm_file * filp)  {  	int err; -	struct xgi_mem_heap *const heap =  -		((index & 0x03) == XGI_MEMLOC_NON_LOCAL)  -		? &info->pcie_heap : &info->fb_heap; -	const u32 offset = (index & ~0x03);  	mutex_lock(&info->dev->struct_mutex); -	err = xgi_mem_free(heap, offset, filp); +	err = drm_sman_free_key(&info->sman, index);  	mutex_unlock(&info->dev->struct_mutex);  	return err; @@ -331,34 +110,14 @@ int xgi_free_ioctl(struct drm_device * dev, void * data,  int xgi_fb_heap_init(struct xgi_info * info)  { -	return xgi_mem_heap_init(&info->fb_heap, XGI_FB_HEAP_START, +	int err; +	 +	mutex_lock(&info->dev->struct_mutex); +	err = drm_sman_set_range(&info->sman, XGI_MEMLOC_LOCAL, +				 XGI_FB_HEAP_START,  				 info->fb.size - XGI_FB_HEAP_START); -} - -/** - * Free all blocks associated with a particular file handle. - */ -void xgi_free_all(struct xgi_info * info, struct xgi_mem_heap * heap, -		  struct drm_file * filp) -{ -	if (!heap->initialized) { -		return; -	} - - -	do { -		struct xgi_mem_block *block; - -		list_for_each_entry(block, &heap->used_list, list) { -			if (block->filp == filp) { -				break; -			} -		} - -		if (&block->list == &heap->used_list) { -			break; -		} +	mutex_unlock(&info->dev->struct_mutex); -		(void) xgi_mem_free(heap, block->offset, filp); -	} while(1); +	info->fb_heap_initialized = (err == 0); +	return err;  } diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index 4ec9b6ff..932615a4 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -131,11 +131,15 @@ int xgi_pcie_heap_init(struct xgi_info * info)  	} -	err = xgi_mem_heap_init(&info->pcie_heap, 0, info->pcie.size); +	mutex_lock(&info->dev->struct_mutex); +	err = drm_sman_set_range(&info->sman, XGI_MEMLOC_NON_LOCAL, +				 0, info->pcie.size); +	mutex_unlock(&info->dev->struct_mutex);  	if (err) {  		xgi_pcie_lut_cleanup(info);  	} +	info->pcie_heap_initialized = (err == 0);  	return err;  } | 
