Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 836cf046 authored by Dave Airlie's avatar Dave Airlie Committed by Dave Airlie
Browse files

drm: cleanup buffer/map code



This is a patch from DRM CVS that cleans up some code that was in CVS
that I never moved to the kernel, this patch produces the result of the
cleanups and puts it into the kernel drm.

From: Eric Anholt <anholt@freebsd.org>, Jon Smirl, Dave Airlie
Signed-off-by: default avatarDave Airlie <airlied@linux.ie>
parent d01cff40
Loading
Loading
Loading
Loading
+7 −2
Original line number Diff line number Diff line
@@ -908,10 +908,11 @@ extern int drm_addbufs_agp(drm_device_t *dev, drm_buf_desc_t *request);
extern int drm_addbufs_pci(drm_device_t *dev, drm_buf_desc_t *request);
extern int drm_addmap(drm_device_t *dev, unsigned int offset,
		      unsigned int size, drm_map_type_t type,
		      drm_map_flags_t flags, drm_map_t **map_ptr);
		      drm_map_flags_t flags, drm_local_map_t **map_ptr);
extern int drm_addmap_ioctl(struct inode *inode, struct file *filp,
			    unsigned int cmd, unsigned long arg);
extern int drm_rmmap(drm_device_t *dev, void *handle);
extern int drm_rmmap(drm_device_t *dev, drm_local_map_t *map);
extern int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map);
extern int drm_rmmap_ioctl(struct inode *inode, struct file *filp,
			   unsigned int cmd, unsigned long arg);

@@ -926,6 +927,10 @@ extern int drm_freebufs( struct inode *inode, struct file *filp,
				    unsigned int cmd, unsigned long arg );
extern int	     drm_mapbufs( struct inode *inode, struct file *filp,
				   unsigned int cmd, unsigned long arg );
extern unsigned long drm_get_resource_start(drm_device_t *dev,
					    unsigned int resource);
extern unsigned long drm_get_resource_len(drm_device_t *dev,
					  unsigned int resource);

				/* DMA support (drm_dma.h) */
extern int	     drm_dma_setup(drm_device_t *dev);
+159 −70
Original line number Diff line number Diff line
@@ -36,29 +36,33 @@
#include <linux/vmalloc.h>
#include "drmP.h"

/**
 * Compute size order.  Returns the exponent of the smaller power of two which
 * is greater or equal to given number.
 * 
 * \param size size.
 * \return order.
 *
 * \todo Can be made faster.
 */
int drm_order( unsigned long size )
unsigned long drm_get_resource_start(drm_device_t *dev, unsigned int resource)
{
	int order;
	unsigned long tmp;
	return pci_resource_start(dev->pdev, resource);
}
EXPORT_SYMBOL(drm_get_resource_start);

	for (order = 0, tmp = size >> 1; tmp; tmp >>= 1, order++)
		;
unsigned long drm_get_resource_len(drm_device_t *dev, unsigned int resource)
{
	return pci_resource_len(dev->pdev, resource);
}
EXPORT_SYMBOL(drm_get_resource_len);

	if (size & (size - 1))
		++order;
static drm_local_map_t *drm_find_matching_map(drm_device_t *dev,
					      drm_local_map_t *map)
{
	struct list_head *list;

	return order;
	list_for_each(list, &dev->maplist->head) {
		drm_map_list_t *entry = list_entry(list, drm_map_list_t, head);
		if (entry->map && map->type == entry->map->type &&
		    entry->map->offset == map->offset) {
			return entry->map;
		}
	}

	return NULL;
}
EXPORT_SYMBOL(drm_order);

#ifdef CONFIG_COMPAT
/*
@@ -89,6 +93,7 @@ int drm_addmap(drm_device_t * dev, unsigned int offset,
	drm_map_t *map;
	drm_map_list_t *list;
	drm_dma_handle_t *dmah;
	drm_local_map_t *found_map;

	map = drm_alloc( sizeof(*map), DRM_MEM_MAPS );
	if ( !map )
@@ -129,6 +134,24 @@ int drm_addmap(drm_device_t * dev, unsigned int offset,
#ifdef __alpha__
		map->offset += dev->hose->mem_space->start;
#endif
		/* Some drivers preinitialize some maps, without the X Server
		 * needing to be aware of it.  Therefore, we just return success
		 * when the server tries to create a duplicate map.
		 */
		found_map = drm_find_matching_map(dev, map);
		if (found_map != NULL) {
			if (found_map->size != map->size) {
				DRM_DEBUG("Matching maps of type %d with "
				   "mismatched sizes, (%ld vs %ld)\n",
				    map->type, map->size, found_map->size);
				found_map->size = map->size;
			}

			drm_free(map, sizeof(*map), DRM_MEM_MAPS);
			*map_ptr = found_map;
			return 0;
		}

		if (drm_core_has_MTRR(dev)) {
			if ( map->type == _DRM_FRAME_BUFFER ||
			     (map->flags & _DRM_WRITE_COMBINING) ) {
@@ -270,55 +293,41 @@ int drm_addmap_ioctl(struct inode *inode, struct file *filp,
 *
 * \sa drm_addmap
 */
int drm_rmmap(drm_device_t *dev, void *handle)
int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map)
{
	struct list_head *list;
	drm_map_list_t *r_list = NULL;
	drm_vma_entry_t *pt, *prev;
	drm_map_t *map;
	int found_maps = 0;
	drm_dma_handle_t dmah;

	down(&dev->struct_sem);
	list = &dev->maplist->head;
	/* Find the list entry for the map and remove it */
	list_for_each(list, &dev->maplist->head) {
		r_list = list_entry(list, drm_map_list_t, head);

		if(r_list->map &&
		   r_list->map->handle == handle &&
		   r_list->map->flags & _DRM_REMOVABLE) break;
		if (r_list->map == map) {
			list_del(list);
			drm_free(list, sizeof(*list), DRM_MEM_MAPS);
			break;
		}
	}

	/* List has wrapped around to the head pointer, or its empty we didn't
	 * find anything.
	/* List has wrapped around to the head pointer, or it's empty and we
	 * didn't find anything.
	 */
	if (list == (&dev->maplist->head)) {
		up(&dev->struct_sem);
		return -EINVAL;
	}
	map = r_list->map;
	list_del(list);
	drm_free(list, sizeof(*list), DRM_MEM_MAPS);

	for (pt = dev->vmalist, prev = NULL; pt; prev = pt, pt = pt->next) {
		if (pt->vma->vm_private_data == map) found_maps++;
	}

	if(!found_maps) {
		drm_dma_handle_t dmah;

	switch (map->type) {
	case _DRM_REGISTERS:
		drm_ioremapfree(map->handle, map->size, dev);
		/* FALLTHROUGH */
	case _DRM_FRAME_BUFFER:
		  if (drm_core_has_MTRR(dev)) {
				if (map->mtrr >= 0) {
		if (drm_core_has_MTRR(dev) && map->mtrr >= 0) {
			int retcode;
					retcode = mtrr_del(map->mtrr,
							   map->offset,
			retcode = mtrr_del(map->mtrr, map->offset,
					   map->size);
			DRM_DEBUG ("mtrr_del=%d\n", retcode);
		}
			}
			drm_ioremapfree(map->handle, map->size, dev);
		break;
	case _DRM_SHM:
		vfree(map->handle);
@@ -334,29 +343,86 @@ int drm_rmmap(drm_device_t *dev, void *handle)
		break;
	}
	drm_free(map, sizeof(*map), DRM_MEM_MAPS);

	return 0;
}
EXPORT_SYMBOL(drm_rmmap_locked);

int drm_rmmap(drm_device_t *dev, drm_local_map_t *map)
{
	int ret;

	down(&dev->struct_sem);
	ret = drm_rmmap_locked(dev, map);
	up(&dev->struct_sem);
	return 0;

	return ret;
}
EXPORT_SYMBOL(drm_rmmap);

/* The rmmap ioctl appears to be unnecessary.  All mappings are torn down on
 * the last close of the device, and this is necessary for cleanup when things
 * exit uncleanly.  Therefore, having userland manually remove mappings seems
 * like a pointless exercise since they're going away anyway.
 *
 * One use case might be after addmap is allowed for normal users for SHM and
 * gets used by drivers that the server doesn't need to care about.  This seems
 * unlikely.
 */
int drm_rmmap_ioctl(struct inode *inode, struct file *filp,
		    unsigned int cmd, unsigned long arg)
{
	drm_file_t *priv = filp->private_data;
	drm_device_t *dev = priv->head->dev;
	drm_map_t request;
	drm_local_map_t *map = NULL;
	struct list_head *list;
	int ret;

	if (copy_from_user(&request, (drm_map_t __user *)arg, sizeof(request))) {
		return -EFAULT;
	}

	return drm_rmmap(dev, request.handle);
	down(&dev->struct_sem);
	list_for_each(list, &dev->maplist->head) {
		drm_map_list_t *r_list = list_entry(list, drm_map_list_t, head);

		if (r_list->map &&
		    r_list->map->handle == request.handle &&
		    r_list->map->flags & _DRM_REMOVABLE) {
			map = r_list->map;
			break;
		}
	}

	/* List has wrapped around to the head pointer, or its empty we didn't
	 * find anything.
	 */
	if (list == (&dev->maplist->head)) {
		up(&dev->struct_sem);
		return -EINVAL;
	}

	if (!map)
		return -EINVAL;

	/* Register and framebuffer maps are permanent */
	if ((map->type == _DRM_REGISTERS) || (map->type == _DRM_FRAME_BUFFER)) {
		up(&dev->struct_sem);
		return 0;
	}

	ret = drm_rmmap_locked(dev, map);

	up(&dev->struct_sem);

	return ret;
}

/**
 * Cleanup after an error on one of the addbufs() functions.
 *
 * \param dev DRM device.
 * \param entry buffer entry where the error occurred.
 *
 * Frees any pages and buffers associated with the given entry.
@@ -1470,3 +1536,26 @@ int drm_mapbufs( struct inode *inode, struct file *filp,
	return retcode;
}

/**
 * Compute size order.  Returns the exponent of the smaller power of two which
 * is greater or equal to given number.
 * 
 * \param size size.
 * \return order.
 *
 * \todo Can be made faster.
 */
int drm_order( unsigned long size )
{
	int order;
	unsigned long tmp;

	for (order = 0, tmp = size >> 1; tmp; tmp >>= 1, order++)
		;

	if (size & (size - 1))
		++order;

	return order;
}
EXPORT_SYMBOL(drm_order);
+16 −52
Original line number Diff line number Diff line
@@ -132,9 +132,7 @@ static drm_ioctl_desc_t drm_ioctls[] = {
int drm_takedown( drm_device_t *dev )
{
	drm_magic_entry_t *pt, *next;
	drm_map_t *map;
	drm_map_list_t *r_list;
	struct list_head *list, *list_next;
	drm_vma_entry_t *vma, *vma_next;
	int i;

@@ -142,6 +140,7 @@ int drm_takedown( drm_device_t *dev )

	if (dev->driver->pretakedown)
	  dev->driver->pretakedown(dev);
	DRM_DEBUG("driver pretakedown completed\n");

	if (dev->unique) {
		drm_free(dev->unique, strlen(dev->unique) + 1, DRM_MEM_DRIVER);
@@ -184,6 +183,10 @@ int drm_takedown( drm_device_t *dev )
		dev->agp->acquired = 0;
		dev->agp->enabled  = 0;
	}
	if (drm_core_check_feature(dev, DRIVER_SG) && dev->sg) {
		drm_sg_cleanup(dev->sg);
		dev->sg = NULL;
	}

				/* Clear vma list (only built for debugging) */
	if ( dev->vmalist ) {
@@ -195,56 +198,11 @@ int drm_takedown( drm_device_t *dev )
	}

	if( dev->maplist ) {
		list_for_each_safe( list, list_next, &dev->maplist->head ) {
			r_list = (drm_map_list_t *)list;

			if ( ( map = r_list->map ) ) {
				drm_dma_handle_t dmah;

				switch ( map->type ) {
				case _DRM_REGISTERS:
				case _DRM_FRAME_BUFFER:
					if (drm_core_has_MTRR(dev)) {
						if ( map->mtrr >= 0 ) {
							int retcode;
							retcode = mtrr_del( map->mtrr,
									    map->offset,
									    map->size );
							DRM_DEBUG( "mtrr_del=%d\n", retcode );
						}
					}
					drm_ioremapfree( map->handle, map->size, dev );
					break;
				case _DRM_SHM:
					vfree(map->handle);
					break;

				case _DRM_AGP:
					/* Do nothing here, because this is all
					 * handled in the AGP/GART driver.
					 */
					break;
				case _DRM_SCATTER_GATHER:
					/* Handle it */
					if (drm_core_check_feature(dev, DRIVER_SG) && dev->sg) {
						drm_sg_cleanup(dev->sg);
						dev->sg = NULL;
					}
					break;
				case _DRM_CONSISTENT:
					dmah.vaddr = map->handle;
					dmah.busaddr = map->offset;
					dmah.size = map->size;
					__drm_pci_free(dev, &dmah);
					break;
		while (!list_empty(&dev->maplist->head)) {
			struct list_head *list = dev->maplist->head.next;
			r_list = list_entry(list, drm_map_list_t, head);
			drm_rmmap_locked(dev, r_list->map);
		}
				drm_free(map, sizeof(*map), DRM_MEM_MAPS);
			}
			list_del( list );
			drm_free(r_list, sizeof(*r_list), DRM_MEM_MAPS);
 		}
		drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS);
		dev->maplist = NULL;
 	}

	if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && dev->queuelist ) {
@@ -273,6 +231,7 @@ int drm_takedown( drm_device_t *dev )
	}
	up( &dev->struct_sem );

	DRM_DEBUG("takedown completed\n");
	return 0;
}

@@ -334,6 +293,11 @@ static void drm_cleanup( drm_device_t *dev )

	drm_takedown( dev );	

	if (dev->maplist) {
		drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS);
		dev->maplist = NULL;
	}

	drm_ctxbitmap_cleanup( dev );
	
	if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) &&
+0 −6
Original line number Diff line number Diff line
@@ -71,12 +71,6 @@ static int drm_setup( drm_device_t *dev )
		dev->magiclist[i].tail = NULL;
	}

	dev->maplist = drm_alloc(sizeof(*dev->maplist),
				  DRM_MEM_MAPS);
	if(dev->maplist == NULL) return -ENOMEM;
	memset(dev->maplist, 0, sizeof(*dev->maplist));
	INIT_LIST_HEAD(&dev->maplist->head);

	dev->ctxlist = drm_alloc(sizeof(*dev->ctxlist),
				  DRM_MEM_CTXLIST);
	if(dev->ctxlist == NULL) return -ENOMEM;
+5 −0
Original line number Diff line number Diff line
@@ -75,6 +75,11 @@ static int drm_fill_in_dev(drm_device_t *dev, struct pci_dev *pdev, const struct
	dev->pci_func = PCI_FUNC(pdev->devfn);
	dev->irq = pdev->irq;

	dev->maplist = drm_calloc(1, sizeof(*dev->maplist), DRM_MEM_MAPS);
	if (dev->maplist == NULL)
		return -ENOMEM;
	INIT_LIST_HEAD(&dev->maplist->head);

	/* the DRM has 6 basic counters */
	dev->counters = 6;
	dev->types[0]  = _DRM_STAT_LOCK;
Loading