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

Commit d1f2b55a authored by Dave Airlie's avatar Dave Airlie Committed by Dave Airlie
Browse files

drm: updated DRM map patch for 32/64 bit systems



I basically combined Paul's patches with additions that I had made
for PCI scatter gather.
I also tried more carefully to avoid problems with the same token
assigned multiple times while trying to use the base address in the
token if possible to gain as much backward compatibility as possible
for broken DRI clients.

From: Paul Mackerras <paulus@samba.org> and Egbert Eich <eich@suse.de>
Signed-off-by: default avatarDave Airlie <airlied@linux.ie>
parent c73681e7
Loading
Loading
Loading
Loading
+6 −8
Original line number Diff line number Diff line
@@ -539,6 +539,7 @@ typedef struct drm_dma_handle {
typedef struct drm_map_list {
	struct list_head	head;	/**< list head */
	drm_map_t		*map;	/**< mapping */
	unsigned int user_token;
} drm_map_list_t;

typedef drm_map_t drm_local_map_t;
@@ -759,6 +760,7 @@ typedef struct drm_device {

	struct            drm_driver *driver;
	drm_local_map_t   *agp_buffer_map;
	unsigned int agp_buffer_token;
	drm_head_t primary;		/**< primary screen head */
} drm_device_t;

@@ -1048,16 +1050,12 @@ static __inline__ void drm_core_ioremapfree(struct drm_map *map, struct drm_devi
		drm_ioremapfree( map->handle, map->size, dev );
}

static __inline__ struct drm_map *drm_core_findmap(struct drm_device *dev, unsigned long offset)
static __inline__ struct drm_map *drm_core_findmap(struct drm_device *dev, unsigned int token)
{
	struct list_head *_list;
	list_for_each( _list, &dev->maplist->head ) {
		drm_map_list_t *_entry = list_entry( _list, drm_map_list_t, head );
		if ( _entry->map &&
		     _entry->map->offset == offset ) {
	drm_map_list_t *_entry;
	list_for_each_entry(_entry, &dev->maplist->head, head)
		if (_entry->user_token == token)
			return _entry->map;
		}
	}
	return NULL;
}

+59 −22
Original line number Diff line number Diff line
@@ -64,13 +64,41 @@ static drm_local_map_t *drm_find_matching_map(drm_device_t *dev,
	return NULL;
}

#ifdef CONFIG_COMPAT
/*
 * Used to allocate 32-bit handles for _DRM_SHM regions
 * The 0x10000000 value is chosen to be out of the way of
 * FB/register and GART physical addresses.
 * Used to allocate 32-bit handles for mappings.
 */
static unsigned int map32_handle = 0x10000000;
#define START_RANGE 0x10000000
#define END_RANGE 0x40000000

#ifdef _LP64
static __inline__ unsigned int HandleID(unsigned long lhandle, drm_device_t *dev) 
{
	static unsigned int map32_handle = START_RANGE;
	unsigned int hash;

	if (lhandle & 0xffffffff00000000) {
		hash = map32_handle;
		map32_handle += PAGE_SIZE;
		if (map32_handle > END_RANGE)
			map32_handle = START_RANGE;
	} else 
		hash = lhandle;

	while (1) {
		drm_map_list_t *_entry;
		list_for_each_entry(_entry, &dev->maplist->head,head) {
			if (_entry->user_token == hash)
				break;
		}
		if (&_entry->head == &dev->maplist->head)
			return hash;

		hash += PAGE_SIZE;
		map32_handle += PAGE_SIZE;
	}
}
#else
# define HandleID(x,dev) (unsigned int)(x)
#endif

/**
@@ -198,7 +226,7 @@ int drm_addmap(drm_device_t * dev, unsigned int offset,
			drm_free(map, sizeof(*map), DRM_MEM_MAPS);
			return -EINVAL;
		}
		map->offset += dev->sg->handle;
		map->offset += (unsigned long)dev->sg->virtual;
		break;
	case _DRM_CONSISTENT: 
		/* dma_addr_t is 64bit on i386 with CONFIG_HIGHMEM64G,
@@ -229,12 +257,11 @@ int drm_addmap(drm_device_t * dev, unsigned int offset,

	down(&dev->struct_sem);
	list_add(&list->head, &dev->maplist->head);
#ifdef CONFIG_COMPAT
	/* Assign a 32-bit handle for _DRM_SHM mappings */
	/* Assign a 32-bit handle */
	/* We do it here so that dev->struct_sem protects the increment */
	if (map->type == _DRM_SHM)
		map->offset = map32_handle += PAGE_SIZE;
#endif
	list->user_token = HandleID(map->type==_DRM_SHM
				    ? (unsigned long)map->handle
				    : map->offset, dev);
 	up(&dev->struct_sem);

	*map_ptr = map;
@@ -251,6 +278,7 @@ int drm_addmap_ioctl(struct inode *inode, struct file *filp,
	drm_map_t *map_ptr;
	drm_map_t __user *argp = (void __user *)arg;
	int err;
	unsigned long handle = 0;

	if (!(filp->f_mode & 3))
		return -EACCES;	/* Require read/write */
@@ -266,13 +294,20 @@ int drm_addmap_ioctl(struct inode *inode, struct file *filp,
		return err;
	}

	{
		drm_map_list_t *_entry;
		list_for_each_entry(_entry, &dev->maplist->head, head) {
			if (_entry->map == map_ptr)
				handle = _entry->user_token;
		}
		if (!handle)
			return -EFAULT;
	}

	if (copy_to_user(argp, map_ptr, sizeof(*map_ptr)))
		return -EFAULT;
	if (map_ptr->type != _DRM_SHM) {
		if (copy_to_user(&argp->handle, &map_ptr->offset,
				 sizeof(map_ptr->offset)))
	if (put_user(handle, &argp->handle))
		return -EFAULT;
	}
	return 0;
	}

@@ -388,7 +423,7 @@ int drm_rmmap_ioctl(struct inode *inode, struct file *filp,
		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->user_token == (unsigned long) request.handle &&
		    r_list->map->flags & _DRM_REMOVABLE) {
			map = r_list->map;
			break;
@@ -939,7 +974,8 @@ static int drm_addbufs_sg(drm_device_t *dev, drm_buf_desc_t *request)

		buf->offset  = (dma->byte_count + offset);
		buf->bus_address = agp_offset + offset;
		buf->address = (void *)(agp_offset + offset + dev->sg->handle);
		buf->address = (void *)(agp_offset + offset 
					+ (unsigned long)dev->sg->virtual);
		buf->next    = NULL;
		buf->waiting = 0;
		buf->pending = 0;
@@ -1456,6 +1492,7 @@ int drm_mapbufs( struct inode *inode, struct file *filp,
		    || (drm_core_check_feature(dev, DRIVER_FB_DMA)
			&& (dma->flags & _DRM_DMA_USE_FB))) {
			drm_map_t *map = dev->agp_buffer_map;
			unsigned long token = dev->agp_buffer_token;

			if ( !map ) {
				retcode = -EINVAL;
@@ -1470,7 +1507,7 @@ int drm_mapbufs( struct inode *inode, struct file *filp,
			virtual = do_mmap( filp, 0, map->size,
					   PROT_READ | PROT_WRITE,
					   MAP_SHARED,
					   (unsigned long)map->offset );
					   token );
#if LINUX_VERSION_CODE <= 0x020402
			up( &current->mm->mmap_sem );
#else
+13 −2
Original line number Diff line number Diff line
@@ -212,6 +212,7 @@ int drm_getsareactx(struct inode *inode, struct file *filp,
	drm_ctx_priv_map_t __user *argp = (void __user *)arg;
	drm_ctx_priv_map_t request;
	drm_map_t *map;
	drm_map_list_t *_entry;

	if (copy_from_user(&request, argp, sizeof(request)))
		return -EFAULT;
@@ -225,7 +226,17 @@ int drm_getsareactx(struct inode *inode, struct file *filp,
	map = dev->context_sareas[request.ctx_id];
	up(&dev->struct_sem);

	request.handle = (void *) map->offset;
	request.handle = 0;
	list_for_each_entry(_entry, &dev->maplist->head,head) {
		if (_entry->map == map) {
			request.handle = (void *)(unsigned long)_entry->user_token;
			break;
		}
	}
	if (request.handle == 0)
		return -EINVAL;


	if (copy_to_user(argp, &request, sizeof(request)))
		return -EFAULT;
	return 0;
@@ -262,7 +273,7 @@ int drm_setsareactx(struct inode *inode, struct file *filp,
	list_for_each(list, &dev->maplist->head) {
		r_list = list_entry(list, drm_map_list_t, head);
		if (r_list->map
		    && r_list->map->offset == (unsigned long) request.handle)
		    && r_list->user_token == (unsigned long) request.handle)
			goto found;
	}
bad:
+1 −1
Original line number Diff line number Diff line
@@ -208,7 +208,7 @@ int drm_getmap( struct inode *inode, struct file *filp,
	map.size   = r_list->map->size;
	map.type   = r_list->map->type;
	map.flags  = r_list->map->flags;
	map.handle = r_list->map->handle;
	map.handle = (void *)(unsigned long) r_list->user_token;
	map.mtrr   = r_list->map->mtrr;
	up(&dev->struct_sem);

+2 −2
Original line number Diff line number Diff line
@@ -235,13 +235,13 @@ static int drm__vm_info(char *buf, char **start, off_t offset, int request,
			type = "??";
		else	
			type = types[map->type];
		DRM_PROC_PRINT("%4d 0x%08lx 0x%08lx %4.4s  0x%02x 0x%08lx ",
		DRM_PROC_PRINT("%4d 0x%08lx 0x%08lx %4.4s  0x%02x 0x%08x ",
			       i,
			       map->offset,
			       map->size,
			       type,
			       map->flags,
			       (unsigned long)map->handle);
			       r_list->user_token);
		if (map->mtrr < 0) {
			DRM_PROC_PRINT("none\n");
		} else {
Loading