summaryrefslogtreecommitdiff
path: root/linux-core
diff options
context:
space:
mode:
Diffstat (limited to 'linux-core')
-rw-r--r--linux-core/drmP.h35
-rw-r--r--linux-core/drm_bo.c566
-rw-r--r--linux-core/drm_drv.c9
-rw-r--r--linux-core/drm_stub.c1
-rw-r--r--linux-core/i915_drv.c5
5 files changed, 381 insertions, 235 deletions
diff --git a/linux-core/drmP.h b/linux-core/drmP.h
index f706d4d8..7e95569b 100644
--- a/linux-core/drmP.h
+++ b/linux-core/drmP.h
@@ -167,6 +167,7 @@
#define DRM_OBJECT_HASH_ORDER 12
#define DRM_FILE_PAGE_OFFSET_START ((0xFFFFFFFFUL >> PAGE_SHIFT) + 1)
#define DRM_FILE_PAGE_OFFSET_SIZE ((0xFFFFFFFFUL >> PAGE_SHIFT) * 16)
+#define DRM_MM_INIT_MAX_PAGES 256
/*@}*/
@@ -660,9 +661,8 @@ typedef struct drm_ref_object {
*/
typedef struct drm_bo_driver{
- int cached_tt;
- int cached_vram;
- drm_local_map_t *vram_map;
+ int cached[DRM_BO_MEM_TYPES];
+ drm_local_map_t *iomap[DRM_BO_MEM_TYPES];
drm_ttm_backend_t *(*create_ttm_backend_entry)
(struct drm_device *dev);
int (*fence_type)(uint32_t flags, uint32_t *class, uint32_t *type);
@@ -801,21 +801,17 @@ typedef struct drm_fence_manager{
} drm_fence_manager_t;
typedef struct drm_buffer_manager{
+ struct mutex init_mutex;
+ int nice_mode;
int initialized;
drm_file_t *last_to_validate;
- int has_vram;
- int has_tt;
- int use_vram;
- int use_tt;
- drm_mm_t tt_manager;
- drm_mm_t vram_manager;
- struct list_head tt_lru;
- struct list_head vram_lru;
- struct list_head tt_pinned;
- struct list_head vram_pinned;
+ int has_type[DRM_BO_MEM_TYPES];
+ int use_type[DRM_BO_MEM_TYPES];
+ drm_mm_t manager[DRM_BO_MEM_TYPES];
+ struct list_head lru[DRM_BO_MEM_TYPES];
+ struct list_head pinned[DRM_BO_MEM_TYPES];
struct list_head unfenced;
struct list_head ddestroy;
- struct list_head other;
struct work_struct wq;
uint32_t fence_type;
unsigned long max_pages;
@@ -1024,10 +1020,10 @@ typedef struct drm_buffer_object{
uint32_t flags;
uint32_t mask;
- drm_mm_node_t *vram;
- drm_mm_node_t *tt;
- struct list_head tt_lru;
- struct list_head vram_lru;
+ drm_mm_node_t *node_ttm; /* MM node for on-card RAM */
+ drm_mm_node_t *node_card; /* MM node for ttm*/
+ struct list_head lru_ttm; /* LRU for the ttm pages*/
+ struct list_head lru_card; /* For memory types with on-card RAM */
struct list_head ddestroy;
uint32_t fence_type;
@@ -1447,7 +1443,8 @@ extern int drm_fence_ioctl(DRM_IOCTL_ARGS);
extern int drm_bo_ioctl(DRM_IOCTL_ARGS);
extern int drm_mm_init_ioctl(DRM_IOCTL_ARGS);
-extern int drm_bo_clean_mm(drm_device_t *dev);
+extern int drm_bo_driver_finish(drm_device_t *dev);
+extern int drm_bo_driver_init(drm_device_t *dev);
extern int drm_fence_buffer_objects(drm_file_t * priv,
struct list_head *list,
uint32_t fence_flags,
diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c
index c24f8d57..20c58f21 100644
--- a/linux-core/drm_bo.c
+++ b/linux-core/drm_bo.c
@@ -59,6 +59,69 @@
(_old) ^= (((_old) ^ (_new)) & (_mask)); \
}
+static inline uint32_t drm_bo_type_flags(unsigned type)
+{
+ return (1 << (24 + type));
+}
+
+static inline drm_buffer_object_t *drm_bo_entry(struct list_head *list,
+ unsigned type)
+{
+ switch(type) {
+ case DRM_BO_MEM_LOCAL:
+ case DRM_BO_MEM_TT:
+ return list_entry(list, drm_buffer_object_t, lru_ttm);
+ case DRM_BO_MEM_VRAM:
+ case DRM_BO_MEM_VRAM_NM:
+ return list_entry(list, drm_buffer_object_t, lru_card);
+ default:
+ BUG_ON(1);
+ }
+ return NULL;
+}
+
+static inline drm_mm_node_t *drm_bo_mm_node(drm_buffer_object_t *bo,
+ unsigned type)
+{
+ switch(type) {
+ case DRM_BO_MEM_LOCAL:
+ case DRM_BO_MEM_TT:
+ return bo->node_ttm;
+ case DRM_BO_MEM_VRAM:
+ case DRM_BO_MEM_VRAM_NM:
+ return bo->node_card;
+ default:
+ BUG_ON(1);
+ }
+ return NULL;
+}
+
+/*
+ * bo locked. dev->struct_mutex locked.
+ */
+
+static void drm_bo_add_to_lru(drm_buffer_object_t *buf,
+ drm_buffer_manager_t *bm)
+{
+ struct list_head *list;
+ unsigned mem_type;
+
+ if (buf->flags & DRM_BO_FLAG_MEM_TT) {
+ mem_type = DRM_BO_MEM_TT;
+ list = (buf->flags & (DRM_BO_FLAG_NO_EVICT | DRM_BO_FLAG_NO_MOVE)) ? &bm->pinned[mem_type] : &bm->lru[mem_type];
+ list_add_tail(&buf->lru_ttm, list);
+ } else {
+ mem_type = DRM_BO_MEM_LOCAL;
+ list = (buf->flags & (DRM_BO_FLAG_NO_EVICT | DRM_BO_FLAG_NO_MOVE)) ? &bm->pinned[mem_type] : &bm->lru[mem_type];
+ list_add_tail(&buf->lru_ttm, list);
+ }
+ if (buf->flags & DRM_BO_FLAG_MEM_VRAM) {
+ mem_type = DRM_BO_MEM_VRAM;
+ list = (buf->flags & (DRM_BO_FLAG_NO_EVICT | DRM_BO_FLAG_NO_MOVE)) ? &bm->pinned[mem_type] : &bm->lru[mem_type];
+ list_add_tail(&buf->lru_card, list);
+ }
+}
+
/*
* bo locked.
*/
@@ -69,27 +132,27 @@ static int drm_move_tt_to_local(drm_buffer_object_t * buf, int evict)
drm_buffer_manager_t *bm = &dev->bm;
int ret;
- BUG_ON(!buf->tt);
-
- mutex_lock(&dev->struct_mutex);
- if (evict)
- ret = drm_evict_ttm(buf->ttm);
- else
- ret = drm_unbind_ttm(buf->ttm);
+ if (buf->node_ttm) {
+ mutex_lock(&dev->struct_mutex);
+ if (evict)
+ ret = drm_evict_ttm(buf->ttm);
+ else
+ ret = drm_unbind_ttm(buf->ttm);
- if (ret) {
+ if (ret) {
+ mutex_unlock(&dev->struct_mutex);
+ if (ret == -EAGAIN)
+ schedule();
+ return ret;
+ }
+
+ drm_mm_put_block(&bm->manager[DRM_BO_MEM_TT], buf->node_ttm);
+ buf->node_ttm = NULL;
mutex_unlock(&dev->struct_mutex);
- if (ret == -EAGAIN)
- schedule();
- return ret;
}
-
- drm_mm_put_block(&bm->tt_manager, buf->tt);
- buf->tt = NULL;
- buf->flags &= ~DRM_BO_MASK_MEM;
+ buf->flags &= ~DRM_BO_FLAG_MEM_TT;
buf->flags |= DRM_BO_FLAG_MEM_LOCAL | DRM_BO_FLAG_CACHED;
- mutex_unlock(&dev->struct_mutex);
return 0;
}
@@ -103,6 +166,7 @@ static void drm_bo_destroy_locked(drm_device_t * dev, drm_buffer_object_t * bo)
drm_buffer_manager_t *bm = &dev->bm;
+
DRM_FLAG_MASKED(bo->priv_flags, 0, _DRM_BO_FLAG_UNFENCED);
/*
@@ -132,8 +196,8 @@ static void drm_bo_destroy_locked(drm_device_t * dev, drm_buffer_object_t * bo)
* Take away from lru lists.
*/
- list_del_init(&bo->tt_lru);
- list_del_init(&bo->vram_lru);
+ list_del_init(&bo->lru_ttm);
+ list_del_init(&bo->lru_card);
if (bo->ttm) {
unsigned long _end = jiffies + DRM_HZ;
@@ -158,14 +222,15 @@ static void drm_bo_destroy_locked(drm_device_t * dev, drm_buffer_object_t * bo)
}
}
- if (bo->tt) {
-
- drm_mm_put_block(&bm->tt_manager, bo->tt);
- bo->tt = NULL;
+ if (bo->node_ttm) {
+ drm_mm_put_block(&bm->manager[DRM_BO_MEM_TT],
+ bo->node_ttm);
+ bo->node_ttm = NULL;
}
- if (bo->vram) {
- drm_mm_put_block(&bm->vram_manager, bo->vram);
- bo->vram = NULL;
+ if (bo->node_card) {
+ drm_mm_put_block(&bm->manager[DRM_BO_MEM_VRAM],
+ bo->node_card);
+ bo->node_card = NULL;
}
if (bo->ttm_object) {
drm_ttm_object_deref_locked(dev, bo->ttm_object);
@@ -246,7 +311,7 @@ static void drm_bo_delayed_workqueue(void *data)
drm_bo_delayed_delete(dev);
mutex_lock(&dev->struct_mutex);
- if (!list_empty(&bm->ddestroy)) {
+ if (bm->initialized && !list_empty(&bm->ddestroy)) {
schedule_delayed_work(&bm->wq,
((DRM_HZ / 100) < 1) ? 1 : DRM_HZ / 100);
}
@@ -296,14 +361,13 @@ int drm_fence_buffer_objects(drm_file_t * priv,
int count = 0;
int ret = 0;
struct list_head f_list, *l;
- struct list_head *q;
mutex_lock(&dev->struct_mutex);
if (!list)
list = &bm->unfenced;
- list_for_each_entry(entry, list, tt_lru) {
+ list_for_each_entry(entry, list, lru_ttm) {
BUG_ON(!(entry->priv_flags & _DRM_BO_FLAG_UNFENCED));
fence_type |= entry->fence_type;
if (entry->fence_class != 0) {
@@ -316,7 +380,6 @@ int drm_fence_buffer_objects(drm_file_t * priv,
}
if (!count) {
- DRM_ERROR("No buffers to fence\n");
ret = -EINVAL;
goto out;
}
@@ -350,13 +413,13 @@ int drm_fence_buffer_objects(drm_file_t * priv,
count = 0;
l = f_list.next;
while (l != &f_list) {
- entry = list_entry(l, drm_buffer_object_t, tt_lru);
+ entry = list_entry(l, drm_buffer_object_t, lru_ttm);
atomic_inc(&entry->usage);
mutex_unlock(&dev->struct_mutex);
mutex_lock(&entry->mutex);
mutex_lock(&dev->struct_mutex);
list_del_init(l);
- list_del_init(&entry->vram_lru);
+ list_del_init(&entry->lru_card);
if (entry->priv_flags & _DRM_BO_FLAG_UNFENCED) {
count++;
if (entry->fence)
@@ -365,17 +428,7 @@ int drm_fence_buffer_objects(drm_file_t * priv,
DRM_FLAG_MASKED(entry->priv_flags, 0,
_DRM_BO_FLAG_UNFENCED);
DRM_WAKEUP(&entry->event_queue);
- if (entry->flags & DRM_BO_FLAG_MEM_TT) {
- q = (entry->flags & DRM_BO_FLAG_NO_EVICT) ?
- &bm->tt_pinned : &bm->tt_lru;
- list_add_tail(&entry->tt_lru, q);
- } else if (entry->flags & DRM_BO_FLAG_MEM_VRAM) {
- q = (entry->flags & DRM_BO_FLAG_NO_EVICT) ?
- &bm->vram_pinned : &bm->vram_lru;
- list_add_tail(&entry->vram_lru, q);
- } else {
- list_add_tail(&entry->tt_lru, &bm->other);
- }
+ drm_bo_add_to_lru(entry, bm);
}
mutex_unlock(&entry->mutex);
drm_bo_usage_deref_locked(dev, entry);
@@ -430,23 +483,24 @@ static int drm_bo_wait(drm_buffer_object_t * bo, int lazy, int ignore_signals,
* bo->mutex locked
*/
-static int drm_bo_evict(drm_buffer_object_t * bo, int tt, int no_wait)
+static int drm_bo_evict(drm_buffer_object_t * bo, unsigned mem_type,
+ int no_wait)
{
int ret = 0;
drm_device_t *dev = bo->dev;
drm_buffer_manager_t *bm = &dev->bm;
+
/*
* Someone might have modified the buffer before we took the buffer mutex.
*/
- if (bo->priv_flags & _DRM_BO_FLAG_UNFENCED)
+ if (bo->priv_flags & _DRM_BO_FLAG_UNFENCED)
goto out;
- if (tt && !bo->tt)
- goto out;
- if (!tt && !bo->vram)
+ if (!(bo->flags & drm_bo_type_flags(mem_type)))
goto out;
ret = drm_bo_wait(bo, 0, 0, no_wait);
+
if (ret) {
if (ret != -EAGAIN)
DRM_ERROR("Failed to expire fence before "
@@ -454,22 +508,26 @@ static int drm_bo_evict(drm_buffer_object_t * bo, int tt, int no_wait)
goto out;
}
- if (tt) {
+ if (mem_type == DRM_BO_MEM_TT) {
ret = drm_move_tt_to_local(bo, 1);
+ if (ret)
+ goto out;
+ mutex_lock(&dev->struct_mutex);
+ list_del(&bo->lru_ttm);
+ list_add_tail(&bo->lru_ttm, &bm->lru[DRM_BO_MEM_LOCAL]);
+ mutex_unlock(&dev->struct_mutex);
}
#if 0
else {
ret = drm_move_vram_to_local(bo);
+ mutex_lock(&dev->struct_mutex);
+ list_del_init(&bo->lru_card);
+ mutex_unlock(&dev->struct_mutex);
}
#endif
if (ret)
goto out;
- mutex_lock(&dev->struct_mutex);
- list_del_init((tt) ? &bo->tt_lru : &bo->vram_lru);
- if (list_empty((tt) ? &bo->vram_lru : &bo->tt_lru))
- list_add_tail(&bo->tt_lru, &bm->other);
- mutex_unlock(&dev->struct_mutex);
DRM_FLAG_MASKED(bo->priv_flags, _DRM_BO_FLAG_EVICTED,
_DRM_BO_FLAG_EVICTED);
out:
@@ -480,13 +538,14 @@ static int drm_bo_evict(drm_buffer_object_t * bo, int tt, int no_wait)
* buf->mutex locked.
*/
-int drm_bo_alloc_space(drm_buffer_object_t * buf, int tt, int no_wait)
+int drm_bo_alloc_space(drm_buffer_object_t * buf, unsigned mem_type,
+ int no_wait)
{
drm_device_t *dev = buf->dev;
drm_mm_node_t *node;
drm_buffer_manager_t *bm = &dev->bm;
drm_buffer_object_t *bo;
- drm_mm_t *mm = (tt) ? &bm->tt_manager : &bm->vram_manager;
+ drm_mm_t *mm = &bm->manager[mem_type];
struct list_head *lru;
unsigned long size = buf->num_pages;
int ret;
@@ -497,20 +556,16 @@ int drm_bo_alloc_space(drm_buffer_object_t * buf, int tt, int no_wait)
if (node)
break;
- lru = (tt) ? &bm->tt_lru : &bm->vram_lru;
+ lru = &bm->lru[mem_type];
if (lru->next == lru)
break;
- if (tt) {
- bo = list_entry(lru->next, drm_buffer_object_t, tt_lru);
- } else {
- bo = list_entry(lru->next, drm_buffer_object_t, vram_lru);
- }
+ bo = drm_bo_entry(lru->next, mem_type);
atomic_inc(&bo->usage);
mutex_unlock(&dev->struct_mutex);
mutex_lock(&bo->mutex);
- ret = drm_bo_evict(bo, tt, no_wait);
+ ret = drm_bo_evict(bo, mem_type, no_wait);
mutex_unlock(&bo->mutex);
drm_bo_usage_deref_unlocked(dev, bo);
if (ret)
@@ -529,10 +584,10 @@ int drm_bo_alloc_space(drm_buffer_object_t * buf, int tt, int no_wait)
BUG_ON(!node);
node->private = (void *)buf;
- if (tt) {
- buf->tt = node;
+ if (mem_type == DRM_BO_MEM_TT) {
+ buf->node_ttm = node;
} else {
- buf->vram = node;
+ buf->node_card = node;
}
buf->offset = node->start * PAGE_SIZE;
return 0;
@@ -545,19 +600,19 @@ static int drm_move_local_to_tt(drm_buffer_object_t * bo, int no_wait)
drm_ttm_backend_t *be;
int ret;
- BUG_ON(bo->tt);
+ BUG_ON(bo->node_ttm);
ret = drm_bo_alloc_space(bo, 1, no_wait);
if (ret)
return ret;
- DRM_DEBUG("Flipping in to AGP 0x%08lx\n", bo->tt->start);
+ DRM_DEBUG("Flipping in to AGP 0x%08lx\n", bo->node_ttm->start);
mutex_lock(&dev->struct_mutex);
ret = drm_bind_ttm(bo->ttm, bo->flags & DRM_BO_FLAG_BIND_CACHED,
- bo->tt->start);
+ bo->node_ttm->start);
if (ret) {
- drm_mm_put_block(&bm->tt_manager, bo->tt);
- bo->tt = NULL;
+ drm_mm_put_block(&bm->manager[DRM_BO_MEM_TT], bo->node_ttm);
+ bo->node_ttm = NULL;
}
mutex_unlock(&dev->struct_mutex);
@@ -589,25 +644,27 @@ static int drm_bo_new_flags(drm_device_t * dev,
uint32_t new_props;
drm_bo_driver_t *driver = dev->driver->bo_driver;
drm_buffer_manager_t *bm = &dev->bm;
+ unsigned i;
/*
- * First adjust the mask.
+ * First adjust the mask to take away nonexistant memory types.
*/
- if (!bm->use_vram)
- new_mask &= ~DRM_BO_FLAG_MEM_VRAM;
- if (!bm->use_tt)
- new_mask &= ~DRM_BO_FLAG_MEM_TT;
+ for (i=0; i<DRM_BO_MEM_TYPES; ++i) {
+ if (!bm->use_type[i])
+ new_mask &= ~drm_bo_type_flags(i);
+ }
if (new_mask & DRM_BO_FLAG_BIND_CACHED) {
- if (((new_mask & DRM_BO_FLAG_MEM_TT) && !driver->cached_tt) &&
+ if (((new_mask & DRM_BO_FLAG_MEM_TT) &&
+ !driver->cached[DRM_BO_MEM_TT]) &&
((new_mask & DRM_BO_FLAG_MEM_VRAM)
- && !driver->cached_vram)) {
+ && !driver->cached[DRM_BO_MEM_VRAM])) {
new_mask &= ~DRM_BO_FLAG_BIND_CACHED;
} else {
- if (!driver->cached_tt)
+ if (!driver->cached[DRM_BO_MEM_TT])
new_flags &= DRM_BO_FLAG_MEM_TT;
- if (!driver->cached_vram)
+ if (!driver->cached[DRM_BO_MEM_VRAM])
new_flags &= DRM_BO_FLAG_MEM_VRAM;
}
}
@@ -766,12 +823,12 @@ static int drm_bo_read_cached(drm_buffer_object_t * bo)
int ret = 0;
BUG_ON(bo->priv_flags & _DRM_BO_FLAG_UNFENCED);
- if (bo->vram)
- ret = drm_bo_evict(bo, 0, 1);
+ if (bo->node_card)
+ ret = drm_bo_evict(bo, DRM_BO_MEM_VRAM, 1);
if (ret)
return ret;
- if (bo->tt)
- ret = drm_bo_evict(bo, 1, 1);
+ if (bo->node_ttm)
+ ret = drm_bo_evict(bo, DRM_BO_MEM_TT, 1);
return ret;
}
@@ -1136,28 +1193,16 @@ static int drm_buffer_object_validate(drm_buffer_object_t * bo,
DRM_FLAG_MASKED(bo->priv_flags, _DRM_BO_FLAG_UNFENCED,
_DRM_BO_FLAG_UNFENCED);
mutex_lock(&dev->struct_mutex);
- list_del(&bo->tt_lru);
- list_add_tail(&bo->tt_lru, &bm->unfenced);
- list_del_init(&bo->vram_lru);
+ list_del(&bo->lru_ttm);
+ list_add_tail(&bo->lru_ttm, &bm->unfenced);
+ list_del_init(&bo->lru_card);
mutex_unlock(&dev->struct_mutex);
} else {
- struct list_head *q;
mutex_lock(&dev->struct_mutex);
- list_del_init(&bo->tt_lru);
- list_del_init(&bo->vram_lru);
-
- if (new_flags & DRM_BO_FLAG_MEM_TT) {
- q = (new_flags & DRM_BO_FLAG_NO_EVICT) ?
- &bm->tt_pinned : &bm->tt_lru;
- list_add_tail(&bo->tt_lru, q);
- } else if (new_flags & DRM_BO_FLAG_MEM_VRAM) {
- q = (new_flags & DRM_BO_FLAG_NO_EVICT) ?
- &bm->vram_pinned : &bm->vram_lru;
- list_add_tail(&bo->vram_lru, q);
- } else {
- list_add_tail(&bo->tt_lru, &bm->other);
- }
+ list_del_init(&bo->lru_ttm);
+ list_del_init(&bo->lru_card);
+ drm_bo_add_to_lru(bo, bm);
mutex_unlock(&dev->struct_mutex);
DRM_FLAG_MASKED(bo->flags, new_flags, DRM_BO_FLAG_NO_EVICT);
}
@@ -1332,15 +1377,14 @@ int drm_buffer_object_create(drm_file_t * priv,
atomic_set(&bo->usage, 1);
atomic_set(&bo->mapped, -1);
DRM_INIT_WAITQUEUE(&bo->event_queue);
- INIT_LIST_HEAD(&bo->tt_lru);
- INIT_LIST_HEAD(&bo->vram_lru);
+ INIT_LIST_HEAD(&bo->lru_ttm);
+ INIT_LIST_HEAD(&bo->lru_card);
INIT_LIST_HEAD(&bo->ddestroy);
- list_add_tail(&bo->tt_lru, &bm->other);
bo->dev = dev;
bo->type = type;
bo->num_pages = num_pages;
- bo->vram = NULL;
- bo->tt = NULL;
+ bo->node_card = NULL;
+ bo->node_ttm = NULL;
if (bo->type == drm_bo_type_fake) {
bo->offset = buffer_start;
bo->buffer_start = 0;
@@ -1540,22 +1584,17 @@ int drm_bo_ioctl(DRM_IOCTL_ARGS)
*/
static void drm_bo_force_list_clean(drm_device_t *dev,
- struct list_head *head, int tt)
+ struct list_head *head,
+ unsigned mem_type)
{
+ drm_buffer_manager_t *bm = &dev->bm;
struct list_head *l;
drm_buffer_object_t *entry;
- int nice_mode = 1;
int ret;
l = head->next;
while (l != head) {
- if (tt) {
- entry = list_entry(l, drm_buffer_object_t,
- tt_lru);
- } else {
- entry = list_entry(l, drm_buffer_object_t,
- vram_lru);
- }
+ entry = drm_bo_entry(l, mem_type);
atomic_inc(&entry->usage);
mutex_unlock(&dev->struct_mutex);
@@ -1566,89 +1605,200 @@ static void drm_bo_force_list_clean(drm_device_t *dev,
*/
if (entry->fence) {
- if (nice_mode) {
+ if (bm->nice_mode) {
unsigned long _end = jiffies + 3*DRM_HZ;
do {
ret = drm_bo_wait(entry, 0, 1, 0);
} while (ret && !time_after_eq(jiffies, _end));
if (entry->fence) {
- nice_mode = 0;
- DRM_ERROR("Detected GPU hang. "
+ bm->nice_mode = 0;
+ DRM_ERROR("Detected GPU hang or "
+ "fence manager was taken down. "
"Evicting waiting buffers\n");
}
}
+
if (entry->fence) {
- drm_fence_usage_deref_unlocked(dev, entry->fence);
+ drm_fence_usage_deref_unlocked(dev,
+ entry->fence);
entry->fence = NULL;
}
}
- ret = drm_bo_evict(entry, tt, 0);
+ ret = drm_bo_evict(entry, mem_type, 0);
if (ret) {
DRM_ERROR("Aargh. Eviction failed.\n");
}
mutex_unlock(&entry->mutex);
mutex_lock(&dev->struct_mutex);
- if (!list_empty(l)) {
- list_del_init(l);
- if (list_empty(&entry->tt_lru) &&
- list_empty(&entry->vram_lru)) {
- list_add_tail(l, &dev->bm.other);
- }
- }
-
drm_bo_usage_deref_locked(dev, entry);
l = head->next;
}
}
-int drm_bo_clean_mm(drm_device_t * dev)
+int drm_bo_clean_mm(drm_device_t * dev, unsigned mem_type)
{
drm_buffer_manager_t *bm = &dev->bm;
- int ret = 0;
+ int ret = -EINVAL;
- mutex_lock(&dev->struct_mutex);
+ if (mem_type >= DRM_BO_MEM_TYPES) {
+ DRM_ERROR("Illegal memory type %d\n", mem_type);
+ return ret;
+ }
- if (!bm->initialized)
- goto out;
+ if (!bm->has_type[mem_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;
- bm->use_vram = 0;
- bm->use_tt = 0;
+ ret = 0;
+ if (mem_type > 0) {
+ drm_bo_force_list_clean(dev, &bm->lru[mem_type], 1);
+ drm_bo_force_list_clean(dev, &bm->pinned[mem_type], 1);
- /*
- * FIXME: Need to handle unfenced list.
- */
+ if (drm_mm_clean(&bm->manager[mem_type])) {
+ drm_mm_takedown(&bm->manager[mem_type]);
+ } else {
+ ret = -EBUSY;
+ }
+ }
- drm_bo_force_list_clean(dev, &bm->tt_lru, 1);
- drm_bo_force_list_clean(dev, &bm->tt_pinned, 1);
- drm_bo_force_list_clean(dev, &bm->vram_lru, 1);
- drm_bo_force_list_clean(dev, &bm->vram_pinned, 1);
+ return ret;
+}
- if (bm->has_vram) {
- if (drm_mm_clean(&bm->vram_manager)) {
- drm_mm_takedown(&bm->vram_manager);
- bm->has_vram = 0;
- } else
- ret = -EBUSY;
+static int drm_bo_init_mm(drm_device_t *dev,
+ unsigned type,
+ unsigned long p_offset,
+ unsigned long p_size)
+{
+ drm_buffer_manager_t *bm = &dev->bm;
+ int ret = -EINVAL;
+
+ if (type >= DRM_BO_MEM_TYPES) {
+ DRM_ERROR("Illegal memory type %d\n", type);
+ return ret;
+ }
+ if (bm->has_type[type]) {
+ DRM_ERROR("Memory manager already initialized for type %d\n",
+ type);
+ return ret;
}
- if (bm->has_tt) {
- if (drm_mm_clean(&bm->tt_manager)) {
- drm_mm_takedown(&bm->tt_manager);
- bm->has_tt = 0;
- } else
- ret = -EBUSY;
+ 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);
+ if (ret)
+ return ret;
+ }
+ bm->has_type[type] = 1;
+ bm->use_type[type] = 1;
+
+ INIT_LIST_HEAD(&bm->lru[type]);
+ INIT_LIST_HEAD(&bm->pinned[type]);
+
+ return 0;
+}
+
- if (!ret)
- bm->initialized = 0;
+/*
+ * call dev->struct_mutex locked;
+ */
+
+static void drm_bo_release_unfenced(drm_buffer_manager_t *bm)
+{
+ struct list_head *list, *next;
+
+ list_for_each_safe(list, next, &bm->unfenced) {
+ list_del(list);
+ list_add_tail(list, &bm->lru[0]);
}
+}
- out:
+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;
+
+ mutex_lock(&dev->bm.init_mutex);
+ mutex_lock(&dev->struct_mutex);
+
+ if (!bm->initialized)
+ goto out;
+ drm_bo_release_unfenced(bm);
+
+ while(i--) {
+ if (bm->has_type[i]) {
+ bm->use_type[i] = 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;
+ }
+ }
mutex_unlock(&dev->struct_mutex);
+ drm_bo_delayed_delete(dev);
+ mutex_lock(&dev->struct_mutex);
+ bm->initialized = 0;
+ mutex_unlock(&dev->struct_mutex);
+ if (!cancel_delayed_work(&bm->wq)) {
+ flush_scheduled_work();
+ }
+ mutex_lock(&dev->struct_mutex);
+ out:
+ mutex_unlock(&dev->struct_mutex);
+ mutex_unlock(&dev->bm.init_mutex);
+ return ret;
+}
+
+
+int drm_bo_driver_init(drm_device_t *dev)
+{
+ drm_bo_driver_t *driver = dev->driver->bo_driver;
+ drm_buffer_manager_t *bm = &dev->bm;
+ int ret = -EINVAL;
+ struct sysinfo si;
+
+ mutex_lock(&dev->bm.init_mutex);
+ mutex_lock(&dev->struct_mutex);
+ if (!driver)
+ goto out_unlock;
+
+ /*
+ * Initialize the system memory buffer type.
+ * Other types need to be driver / IOCTL initialized.
+ */
+ ret = drm_bo_init_mm(dev, 0, 0, 0);
+ if (ret)
+ goto out_unlock;
+
+ INIT_WORK(&bm->wq, &drm_bo_delayed_workqueue, dev);
+ bm->initialized = 1;
+ bm->nice_mode = 1;
+ atomic_set(&bm->count, 0);
+ bm->cur_pages = 0;
+ si_meminfo(&si);
+ bm->max_pages = si.totalram >> 1;
+ INIT_LIST_HEAD(&bm->unfenced);
+ INIT_LIST_HEAD(&bm->ddestroy);
+ out_unlock:
+ mutex_unlock(&dev->struct_mutex);
+ mutex_unlock(&dev->bm.init_mutex);
return ret;
}
+EXPORT_SYMBOL(drm_bo_driver_init);
+
int drm_mm_init_ioctl(DRM_IOCTL_ARGS)
{
@@ -1668,71 +1818,69 @@ int drm_mm_init_ioctl(DRM_IOCTL_ARGS)
switch (arg.req.op) {
case mm_init:
- if (bm->initialized) {
- DRM_ERROR("Memory manager already initialized\n");
- return -EINVAL;
- }
+ ret = -EINVAL;
+ mutex_lock(&dev->bm.init_mutex);
mutex_lock(&dev->struct_mutex);
- bm->has_vram = 0;
- bm->has_tt = 0;
-
- if (arg.req.vr_p_size) {
- ret = drm_mm_init(&bm->vram_manager,
- arg.req.vr_p_offset,
- arg.req.vr_p_size);
- bm->has_vram = 1;
- /*
- * VRAM not supported yet.
- */
-
- bm->use_vram = 0;
- if (ret)
- break;
+ if (!bm->initialized) {
+ DRM_ERROR("DRM memory manager was not initialized.\n");
+ break;
}
-
- if (arg.req.tt_p_size) {
- ret = drm_mm_init(&bm->tt_manager,
- arg.req.tt_p_offset,
- arg.req.tt_p_size);
- bm->has_tt = 1;
- bm->use_tt = 1;
-
- if (ret) {
- if (bm->has_vram)
- drm_mm_takedown(&bm->vram_manager);
- break;
- }
+ if (arg.req.mem_type == 0) {
+ DRM_ERROR("System memory buffers already initialized.\n");
+ break;
}
- arg.rep.mm_sarea = 0;
-
- INIT_LIST_HEAD(&bm->vram_lru);
- INIT_LIST_HEAD(&bm->tt_lru);
- INIT_LIST_HEAD(&bm->vram_pinned);
- INIT_LIST_HEAD(&bm->tt_pinned);
- INIT_LIST_HEAD(&bm->unfenced);
- INIT_LIST_HEAD(&bm->ddestroy);
- INIT_LIST_HEAD(&bm->other);
-
- INIT_WORK(&bm->wq, &drm_bo_delayed_workqueue, dev);
- bm->initialized = 1;
- atomic_set(&bm->count, 0);
- bm->cur_pages = 0;
- bm->max_pages = arg.req.max_locked_pages;
- mutex_unlock(&dev->struct_mutex);
+ ret = drm_bo_init_mm(dev, arg.req.mem_type,
+ arg.req.p_offset,
+ arg.req.p_size);
break;
case mm_takedown:
LOCK_TEST_WITH_RETURN(dev, filp);
- if (drm_bo_clean_mm(dev)) {
- DRM_ERROR("Memory manager not clean. "
- "Delaying takedown\n");
+ mutex_lock(&dev->bm.init_mutex);
+ mutex_lock(&dev->struct_mutex);
+ ret = -EINVAL;
+ if (!bm->initialized) {
+ DRM_ERROR("DRM memory manager was not initialized\n");
+ break;
+ }
+ if (arg.req.mem_type == 0) {
+ DRM_ERROR("No takedown for System memory buffers.\n");
+ break;
+ }
+ ret = 0;
+ if (drm_bo_clean_mm(dev, arg.req.mem_type)) {
+ DRM_ERROR("Memory manager type %d not clean. "
+ "Delaying takedown\n", arg.req.mem_type);
}
- DRM_DEBUG("We have %ld still locked pages\n", bm->cur_pages);
break;
+ case mm_set_max_pages: {
+ struct sysinfo si;
+ mutex_lock(&dev->bm.init_mutex);
+ mutex_lock(&dev->struct_mutex);
+ if (arg.req.p_size < bm->cur_pages) {
+ DRM_ERROR("Cannot currently decrease max number of "
+ "locked pages below the number currently "
+ "locked.\n");
+ ret = -EINVAL;
+ break;
+ }
+ si_meminfo(&si);
+ if (arg.req.p_size > si.totalram) {
+ DRM_ERROR("Cannot set max number of locked pages "
+ "to %lu since the total number of RAM pages "
+ "is %lu.\n", (unsigned long) arg.req.p_size,
+ (unsigned long) si.totalram);
+ ret = -EINVAL;
+ break;
+ }
+ bm->max_pages = arg.req.p_size;
+ }
default:
DRM_ERROR("Function not implemented yet\n");
return -EINVAL;
}
+ mutex_unlock(&dev->struct_mutex);
+ mutex_unlock(&dev->bm.init_mutex);
if (ret)
return ret;
diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c
index c7f0f485..43b4f8d4 100644
--- a/linux-core/drm_drv.c
+++ b/linux-core/drm_drv.c
@@ -149,6 +149,11 @@ int drm_lastclose(drm_device_t * dev)
DRM_DEBUG("\n");
+ if (drm_bo_driver_finish(dev)) {
+ DRM_ERROR("DRM memory manager still busy. "
+ "System is unstable. Please reboot.\n");
+ }
+
if (dev->driver->lastclose)
dev->driver->lastclose(dev);
DRM_DEBUG("driver lastclose completed\n");
@@ -265,10 +270,6 @@ int drm_lastclose(drm_device_t * dev)
dev->dev_mapping = NULL;
mutex_unlock(&dev->struct_mutex);
- if (drm_bo_clean_mm(dev)) {
- DRM_ERROR("DRM memory manager still busy. "
- "System is unstable. Please reboot.\n");
- }
DRM_DEBUG("lastclose completed\n");
return 0;
}
diff --git a/linux-core/drm_stub.c b/linux-core/drm_stub.c
index e3db07dc..66310560 100644
--- a/linux-core/drm_stub.c
+++ b/linux-core/drm_stub.c
@@ -71,6 +71,7 @@ static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev,
init_timer(&dev->timer);
mutex_init(&dev->struct_mutex);
mutex_init(&dev->ctxlist_mutex);
+ mutex_init(&dev->bm.init_mutex);
dev->pdev = pdev;
diff --git a/linux-core/i915_drv.c b/linux-core/i915_drv.c
index 1263bcab..2c5b43d0 100644
--- a/linux-core/i915_drv.c
+++ b/linux-core/i915_drv.c
@@ -51,9 +51,8 @@ static drm_fence_driver_t i915_fence_driver = {
#endif
#ifdef I915_HAVE_BUFFER
static drm_bo_driver_t i915_bo_driver = {
- .vram_map = NULL,
- .cached_vram = 0,
- .cached_tt = 1,
+ .iomap = {NULL, NULL},
+ .cached = {1, 1},
.create_ttm_backend_entry = i915_create_ttm_backend_entry,
.fence_type = i915_fence_types,
.invalidate_caches = i915_invalidate_caches