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.
#define DRM_MEM_HASHTAB 23
#define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8)
+#define DRM_MAP_HASH_OFFSET 0x10000000
/*@}*/
*/
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;
/*@{ */
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 */
/*@{ */
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.
*
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;
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;
}
#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;
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;
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
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;
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));
)
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;
#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,
#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