Change drm Map handles to be arbitrary 32-bit hash tokens in the range
0x10000000 to 0x90000000 in PAGE_SIZE increments. Implement hashed map lookups. This potentially breaks both 2D and 3D drivers. If so, the corresponding 2D and 3D driver should be fixed, and it's corresponding drm device driver should have its major bumped as soon as possible. Bump sis and via drm device driver majors. The SiS and Unichrome 3D drivers are fixed in Mesa CVS HEAD and mesa_6_4_branch.main
parent
c21a7b763a
commit
a392349691
|
@ -153,6 +153,7 @@
|
|||
#define DRM_MEM_HASHTAB 23
|
||||
|
||||
#define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8)
|
||||
#define DRM_MAP_HASH_OFFSET 0x10000000
|
||||
|
||||
/*@}*/
|
||||
|
||||
|
@ -502,6 +503,7 @@ typedef struct drm_sigdata {
|
|||
*/
|
||||
typedef struct drm_map_list {
|
||||
struct list_head head; /**< list head */
|
||||
drm_hash_item_t hash;
|
||||
drm_map_t *map; /**< mapping */
|
||||
unsigned int user_token;
|
||||
} drm_map_list_t;
|
||||
|
@ -679,6 +681,7 @@ typedef struct drm_device {
|
|||
/*@{ */
|
||||
drm_map_list_t *maplist; /**< Linked list of regions */
|
||||
int map_count; /**< Number of mappable regions */
|
||||
drm_open_hash_t map_hash; /**< User token hash table for maps */
|
||||
|
||||
/** \name Context handle management */
|
||||
/*@{ */
|
||||
|
|
|
@ -65,44 +65,6 @@ static drm_map_list_t *drm_find_matching_map(drm_device_t *dev,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Used to allocate 32-bit handles for mappings.
|
||||
*/
|
||||
#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
|
||||
|
||||
/**
|
||||
* Ioctl to specify a range of memory that is available for mapping by a non-root process.
|
||||
*
|
||||
|
@ -300,9 +262,18 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset,
|
|||
list_add(&list->head, &dev->maplist->head);
|
||||
/* Assign a 32-bit handle */
|
||||
/* We do it here so that dev->struct_sem protects the increment */
|
||||
list->user_token = HandleID(map->type == _DRM_SHM
|
||||
? (unsigned long)map->handle
|
||||
: map->offset, dev);
|
||||
|
||||
if (drm_ht_just_insert_please(&dev->map_hash, &list->hash,
|
||||
((map->type == _DRM_SHM) ? (unsigned long)map->handle :
|
||||
map->offset) >> PAGE_SHIFT,
|
||||
32 - PAGE_SHIFT - 1)) {
|
||||
drm_free(map, sizeof(*map), DRM_MEM_MAPS);
|
||||
drm_free(list, sizeof(*list), DRM_MEM_MAPS);
|
||||
up(&dev->struct_sem);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
list->user_token = (list->hash.key << PAGE_SHIFT) + DRM_MAP_HASH_OFFSET;
|
||||
up(&dev->struct_sem);
|
||||
|
||||
*maplist = list;
|
||||
|
@ -387,6 +358,8 @@ int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map)
|
|||
|
||||
if (r_list->map == map) {
|
||||
list_del(list);
|
||||
drm_ht_remove_key(&dev->map_hash,
|
||||
(r_list->user_token - DRM_MAP_HASH_OFFSET) >> PAGE_SHIFT);
|
||||
drm_free(list, sizeof(*list), DRM_MEM_MAPS);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
#ifndef DRM_HASHTAB_H
|
||||
#define DRM_HASHTAB_H
|
||||
|
||||
#define drm_hash_entry(_a1, _a2, _a3) list_entry(_a1, _a2, _a3)
|
||||
#define drm_hash_entry(_ptr, _type, _member) container_of(_ptr, _type, _member)
|
||||
|
||||
typedef struct drm_hash_item{
|
||||
struct hlist_node head;
|
||||
|
|
|
@ -82,6 +82,10 @@ static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev,
|
|||
if (dev->maplist == NULL)
|
||||
return -ENOMEM;
|
||||
INIT_LIST_HEAD(&dev->maplist->head);
|
||||
if (drm_ht_create(&dev->map_hash, 12)) {
|
||||
drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* the DRM has 6 counters */
|
||||
dev->counters = 6;
|
||||
|
|
|
@ -59,7 +59,7 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,
|
|||
drm_device_t *dev = priv->head->dev;
|
||||
drm_map_t *map = NULL;
|
||||
drm_map_list_t *r_list;
|
||||
struct list_head *list;
|
||||
drm_hash_item_t *hash;
|
||||
|
||||
/*
|
||||
* Find the right map
|
||||
|
@ -70,14 +70,12 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,
|
|||
if (!dev->agp || !dev->agp->cant_use_aperture)
|
||||
goto vm_nopage_error;
|
||||
|
||||
list_for_each(list, &dev->maplist->head) {
|
||||
r_list = list_entry(list, drm_map_list_t, head);
|
||||
map = r_list->map;
|
||||
if (!map)
|
||||
continue;
|
||||
if (r_list->user_token == VM_OFFSET(vma))
|
||||
break;
|
||||
}
|
||||
if (drm_ht_find_item(&dev->map_hash, (VM_OFFSET(vma) - DRM_MAP_HASH_OFFSET) >> PAGE_SHIFT,
|
||||
&hash))
|
||||
goto vm_nopage_error;
|
||||
|
||||
r_list = drm_hash_entry(hash, drm_map_list_t, hash);
|
||||
map = r_list->map;
|
||||
|
||||
if (map && map->type == _DRM_AGP) {
|
||||
unsigned long offset = address - vma->vm_start;
|
||||
|
@ -556,9 +554,8 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
|
|||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_map_t *map = NULL;
|
||||
drm_map_list_t *r_list;
|
||||
unsigned long offset = 0;
|
||||
struct list_head *list;
|
||||
drm_hash_item_t *hash;
|
||||
|
||||
DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n",
|
||||
vma->vm_start, vma->vm_end, VM_OFFSET(vma));
|
||||
|
@ -578,22 +575,13 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
|
|||
)
|
||||
return drm_mmap_dma(filp, vma);
|
||||
|
||||
/* A sequential search of a linked list is
|
||||
fine here because: 1) there will only be
|
||||
about 5-10 entries in the list and, 2) a
|
||||
DRI client only has to do this mapping
|
||||
once, so it doesn't have to be optimized
|
||||
for performance, even if the list was a
|
||||
bit longer. */
|
||||
list_for_each(list, &dev->maplist->head) {
|
||||
|
||||
r_list = list_entry(list, drm_map_list_t, head);
|
||||
map = r_list->map;
|
||||
if (!map)
|
||||
continue;
|
||||
if (r_list->user_token == VM_OFFSET(vma))
|
||||
break;
|
||||
}
|
||||
if (drm_ht_find_item(&dev->map_hash, (VM_OFFSET(vma) - DRM_MAP_HASH_OFFSET) >> PAGE_SHIFT,
|
||||
&hash)) {
|
||||
DRM_ERROR("Could not find map\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
map = drm_hash_entry(hash,drm_map_list_t, hash)->map;
|
||||
|
||||
if (!map || ((map->flags & _DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN)))
|
||||
return -EPERM;
|
||||
|
|
|
@ -35,9 +35,9 @@
|
|||
#define DRIVER_NAME "sis"
|
||||
#define DRIVER_DESC "SIS 300/630/540"
|
||||
#define DRIVER_DATE "20060704"
|
||||
#define DRIVER_MAJOR 1
|
||||
#define DRIVER_MINOR 2
|
||||
#define DRIVER_PATCHLEVEL 1
|
||||
#define DRIVER_MAJOR 2
|
||||
#define DRIVER_MINOR 0
|
||||
#define DRIVER_PATCHLEVEL 0
|
||||
|
||||
enum sis_family {
|
||||
SIS_OTHER = 0,
|
||||
|
|
|
@ -44,9 +44,9 @@
|
|||
|
||||
#define VIA_DRM_DRIVER_DATE "20060616"
|
||||
|
||||
#define VIA_DRM_DRIVER_MAJOR 2
|
||||
#define VIA_DRM_DRIVER_MINOR 10
|
||||
#define VIA_DRM_DRIVER_PATCHLEVEL 2
|
||||
#define VIA_DRM_DRIVER_MAJOR 3
|
||||
#define VIA_DRM_DRIVER_MINOR 0
|
||||
#define VIA_DRM_DRIVER_PATCHLEVEL 0
|
||||
#define VIA_DRM_DRIVER_VERSION (((VIA_DRM_DRIVER_MAJOR) << 16) | (VIA_DRM_DRIVER_MINOR))
|
||||
|
||||
#define VIA_NR_SAREA_CLIPRECTS 8
|
||||
|
|
Loading…
Reference in New Issue