summaryrefslogtreecommitdiff
path: root/linux-core/drm_bo.c
diff options
context:
space:
mode:
authorThomas Hellstrom <thomas-at-tungstengraphics-dot-com>2007-01-31 14:50:57 +0100
committerThomas Hellstrom <thomas-at-tungstengraphics-dot-com>2007-01-31 14:50:57 +0100
commit3024f23c6551e219b0236041a8205bf1bc60ed94 (patch)
tree87bd9deef4a55bf887a8c0978a5ad18412bc13e5 /linux-core/drm_bo.c
parent07fabc3fd8f00006e6117081f5183a826a6d2bbb (diff)
memory manager: Make device driver aware of different memory types.
Memory types are either fixed (on-card or pre-bound AGP) or not fixed (dynamically bound) to an aperture. They also carry information about: 1) Whether they can be mapped cached. 2) Whether they are at all mappable. 3) Whether they need an ioremap to be accessible from kernel space. In this way VRAM memory and, for example, pre-bound AGP appear identical to the memory manager. This also makes support for unmappable VRAM simple to implement.
Diffstat (limited to 'linux-core/drm_bo.c')
-rw-r--r--linux-core/drm_bo.c87
1 files changed, 52 insertions, 35 deletions
diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c
index 2b960c75..b72e9912 100644
--- a/linux-core/drm_bo.c
+++ b/linux-core/drm_bo.c
@@ -74,8 +74,10 @@ static void drm_bo_add_to_lru(drm_buffer_object_t * bo,
drm_buffer_manager_t * bm)
{
struct list_head *list;
- bo->mem_type = 0;
+ drm_mem_type_manager_t *man;
+ bo->mem_type = 0;
+
switch(bo->flags & DRM_BO_MASK_MEM) {
case DRM_BO_FLAG_MEM_TT:
bo->mem_type = DRM_BO_MEM_TT;
@@ -89,8 +91,10 @@ static void drm_bo_add_to_lru(drm_buffer_object_t * bo,
default:
BUG_ON(1);
}
+
+ man = &bm->man[bo->mem_type];
list = (bo->flags & (DRM_BO_FLAG_NO_EVICT | DRM_BO_FLAG_NO_MOVE)) ?
- &bm->pinned[bo->mem_type] : &bm->lru[bo->mem_type];
+ &man->pinned : &man->lru;
list_add_tail(&bo->lru, list);
return;
}
@@ -543,7 +547,8 @@ int drm_bo_alloc_space(drm_buffer_object_t * bo, unsigned mem_type,
drm_mm_node_t *node;
drm_buffer_manager_t *bm = &dev->bm;
drm_buffer_object_t *entry;
- drm_mm_t *mm = &bm->manager[mem_type];
+ drm_mem_type_manager_t *man = &bm->man[mem_type];
+ drm_mm_t *mm = &man->manager;
struct list_head *lru;
unsigned long size = bo->num_pages;
int ret;
@@ -554,7 +559,7 @@ int drm_bo_alloc_space(drm_buffer_object_t * bo, unsigned mem_type,
if (node)
break;
- lru = &bm->lru[mem_type];
+ lru = &man->lru;
if (lru->next == lru)
break;
@@ -638,7 +643,6 @@ static int drm_bo_new_flags(drm_device_t * dev,
{
uint32_t new_flags = 0;
uint32_t new_props;
- drm_bo_driver_t *driver = dev->driver->bo_driver;
drm_buffer_manager_t *bm = &dev->bm;
unsigned i;
@@ -647,7 +651,7 @@ static int drm_bo_new_flags(drm_device_t * dev,
*/
for (i = 0; i < DRM_BO_MEM_TYPES; ++i) {
- if (!bm->use_type[i])
+ if (!bm->man[i].use_type)
new_mask &= ~drm_bo_type_flags(i);
}
@@ -659,14 +663,18 @@ static int drm_bo_new_flags(drm_device_t * dev,
}
if (new_mask & DRM_BO_FLAG_BIND_CACHED) {
if (((new_mask & DRM_BO_FLAG_MEM_TT) &&
- !driver->cached[DRM_BO_MEM_TT]) &&
- ((new_mask & DRM_BO_FLAG_MEM_VRAM)
- && !driver->cached[DRM_BO_MEM_VRAM])) {
+ !(bm->man[DRM_BO_MEM_TT].flags &
+ _DRM_FLAG_MEMTYPE_CACHED) &&
+ ((new_mask & DRM_BO_FLAG_MEM_VRAM)
+ && !(bm->man[DRM_BO_MEM_VRAM].flags &
+ _DRM_FLAG_MEMTYPE_CACHED)))) {
new_mask &= ~DRM_BO_FLAG_BIND_CACHED;
} else {
- if (!driver->cached[DRM_BO_MEM_TT])
+ if (!(bm->man[DRM_BO_MEM_TT].flags &
+ _DRM_FLAG_MEMTYPE_CACHED))
new_flags &= DRM_BO_FLAG_MEM_TT;
- if (!driver->cached[DRM_BO_MEM_VRAM])
+ if (!(bm->man[DRM_BO_MEM_VRAM].flags &
+ _DRM_FLAG_MEMTYPE_CACHED))
new_flags &= DRM_BO_FLAG_MEM_VRAM;
}
}
@@ -1735,6 +1743,8 @@ static int drm_bo_force_list_clean(drm_device_t * dev,
int drm_bo_clean_mm(drm_device_t * dev, unsigned mem_type)
{
drm_buffer_manager_t *bm = &dev->bm;
+ drm_mem_type_manager_t *man = &bm->man[mem_type];
+ drm_mem_type_manager_t *local_man = &bm->man[DRM_BO_MEM_LOCAL];
int ret = -EINVAL;
if (mem_type >= DRM_BO_MEM_TYPES) {
@@ -1742,13 +1752,13 @@ int drm_bo_clean_mm(drm_device_t * dev, unsigned mem_type)
return ret;
}
- if (!bm->has_type[mem_type]) {
+ if (!man->has_type) {
DRM_ERROR("Trying to take down uninitialized "
"memory manager type\n");
return ret;
}
- bm->use_type[mem_type] = 0;
- bm->has_type[mem_type] = 0;
+ man->use_type = 0;
+ man->has_type = 0;
ret = 0;
if (mem_type > 0) {
@@ -1763,15 +1773,12 @@ int drm_bo_clean_mm(drm_device_t * dev, unsigned mem_type)
* Throw out evicted no-move buffers.
*/
- drm_bo_force_list_clean(dev, &bm->pinned[DRM_BO_MEM_LOCAL],
- mem_type, 1, 0);
- drm_bo_force_list_clean(dev, &bm->lru[mem_type], mem_type, 1,
- 0);
- drm_bo_force_list_clean(dev, &bm->pinned[mem_type], mem_type, 1,
- 0);
+ drm_bo_force_list_clean(dev, &local_man->pinned, mem_type, 1, 0);
+ drm_bo_force_list_clean(dev, &man->lru, mem_type, 1, 0);
+ drm_bo_force_list_clean(dev, &man->pinned, mem_type, 1, 0);
- if (drm_mm_clean(&bm->manager[mem_type])) {
- drm_mm_takedown(&bm->manager[mem_type]);
+ if (drm_mm_clean(&man->manager)) {
+ drm_mm_takedown(&man->manager);
} else {
ret = -EBUSY;
}
@@ -1784,6 +1791,7 @@ static int drm_bo_lock_mm(drm_device_t * dev, unsigned mem_type)
{
int ret;
drm_buffer_manager_t *bm = &dev->bm;
+ drm_mem_type_manager_t *man = &bm->man[mem_type];
if (mem_type == 0 || mem_type >= DRM_BO_MEM_TYPES) {
DRM_ERROR("Illegal memory manager memory type %u,\n", mem_type);
@@ -1793,11 +1801,11 @@ static int drm_bo_lock_mm(drm_device_t * dev, unsigned mem_type)
ret = drm_bo_force_list_clean(dev, &bm->unfenced, mem_type, 0, 1);
if (ret)
return ret;
- ret = drm_bo_force_list_clean(dev, &bm->lru[mem_type], mem_type, 0, 1);
+ ret = drm_bo_force_list_clean(dev, &man->lru, mem_type, 0, 1);
if (ret)
return ret;
ret =
- drm_bo_force_list_clean(dev, &bm->pinned[mem_type], mem_type, 0, 1);
+ drm_bo_force_list_clean(dev, &man->pinned, mem_type, 0, 1);
return ret;
}
@@ -1807,32 +1815,39 @@ static int drm_bo_init_mm(drm_device_t * dev,
{
drm_buffer_manager_t *bm = &dev->bm;
int ret = -EINVAL;
+ drm_mem_type_manager_t *man;
if (type >= DRM_BO_MEM_TYPES) {
DRM_ERROR("Illegal memory type %d\n", type);
return ret;
}
- if (bm->has_type[type]) {
+
+ man = &bm->man[type];
+ if (man->has_type) {
DRM_ERROR("Memory manager already initialized for type %d\n",
type);
return ret;
}
+ ret = dev->driver->bo_driver->init_mem_type(dev, type, man);
+ if (ret)
+ return ret;
+
ret = 0;
if (type != DRM_BO_MEM_LOCAL) {
if (!p_size) {
DRM_ERROR("Zero size memory manager type %d\n", type);
return ret;
}
- ret = drm_mm_init(&bm->manager[type], p_offset, p_size);
+ ret = drm_mm_init(&man->manager, p_offset, p_size);
if (ret)
return ret;
}
- bm->has_type[type] = 1;
- bm->use_type[type] = 1;
+ man->has_type = 1;
+ man->use_type = 1;
- INIT_LIST_HEAD(&bm->lru[type]);
- INIT_LIST_HEAD(&bm->pinned[type]);
+ INIT_LIST_HEAD(&man->lru);
+ INIT_LIST_HEAD(&man->pinned);
return 0;
}
@@ -1847,6 +1862,7 @@ int drm_bo_driver_finish(drm_device_t * dev)
drm_buffer_manager_t *bm = &dev->bm;
int ret = 0;
unsigned i = DRM_BO_MEM_TYPES;
+ drm_mem_type_manager_t *man;
mutex_lock(&dev->bm.init_mutex);
mutex_lock(&dev->struct_mutex);
@@ -1856,14 +1872,15 @@ int drm_bo_driver_finish(drm_device_t * dev)
bm->initialized = 0;
while (i--) {
- if (bm->has_type[i]) {
- bm->use_type[i] = 0;
+ man = &bm->man[i];
+ if (man->has_type) {
+ man->use_type = 0;
if ((i != DRM_BO_MEM_LOCAL) && drm_bo_clean_mm(dev, i)) {
ret = -EBUSY;
DRM_ERROR("DRM memory manager type %d "
"is not clean.\n", i);
}
- bm->has_type[i] = 0;
+ man->has_type = 0;
}
}
mutex_unlock(&dev->struct_mutex);
@@ -1875,10 +1892,10 @@ int drm_bo_driver_finish(drm_device_t * dev)
if (list_empty(&bm->ddestroy)) {
DRM_DEBUG("Delayed destroy list was clean\n");
}
- if (list_empty(&bm->lru[0])) {
+ if (list_empty(&bm->man[0].lru)) {
DRM_DEBUG("Swap list was clean\n");
}
- if (list_empty(&bm->pinned[0])) {
+ if (list_empty(&bm->man[0].pinned)) {
DRM_DEBUG("NO_MOVE list was clean\n");
}
if (list_empty(&bm->unfenced)) {