On Tue, 2009-12-08 at 15:33 +0100, Jerome Glisse wrote: > This change allow driver to pass sorted memory placement, > from most prefered placement to least prefered placement. > In order to avoid long function prototype a structure is > used to gather memory placement informations such as range > restriction (if you need a buffer to be in given range). > Range restriction is determined by fpfn & lpfn which are > the first page and last page number btw which allocation > can happen. If those fields are set to 0 ttm will assume > buffer can be put anywhere in the address space (thus it > avoids putting a burden on the driver to always properly > set those fields). > > This patch also factor few functions like evicting first > entry of lru list or getting a memory space. This avoid > code duplication. > > V2: Change API to use placement flags and array instead > of packing placement order into a quadword. > V3: Make sure we set the appropriate mem.placement flag > when validating or allocation memory space. A way to pass fpfn/lpfn to ttm_buffer_object_{init,create}() would be really useful too. Perhaps passing a struct ttm_placement rather than flags to these functions?
Ben. > > Signed-off-by: Jerome Glisse <jgli...@redhat.com> > --- > drivers/gpu/drm/ttm/ttm_bo.c | 463 > +++++++++++++++++++-------------------- > include/drm/ttm/ttm_bo_api.h | 42 +++- > include/drm/ttm/ttm_bo_driver.h | 20 +-- > 3 files changed, 256 insertions(+), 269 deletions(-) > > diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c > index 87c0625..9476bde 100644 > --- a/drivers/gpu/drm/ttm/ttm_bo.c > +++ b/drivers/gpu/drm/ttm/ttm_bo.c > @@ -27,6 +27,14 @@ > /* > * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com> > */ > +/* Notes: > + * > + * We store bo pointer in drm_mm_node struct so we know which bo own a > + * specific node. There is no protection on the pointer, thus to make > + * sure things don't go berserk you have to access this pointer while > + * holding the global lru lock and make sure anytime you free a node you > + * reset the pointer to NULL. > + */ > > #include "ttm/ttm_module.h" > #include "ttm/ttm_bo_driver.h" > @@ -247,7 +255,6 @@ EXPORT_SYMBOL(ttm_bo_unreserve); > /* > * Call bo->mutex locked. > */ > - > static int ttm_bo_add_ttm(struct ttm_buffer_object *bo, bool zero_alloc) > { > struct ttm_bo_device *bdev = bo->bdev; > @@ -328,14 +335,8 @@ static int ttm_bo_handle_move_mem(struct > ttm_buffer_object *bo, > } > > if (bo->mem.mem_type == TTM_PL_SYSTEM) { > - > - struct ttm_mem_reg *old_mem = &bo->mem; > - uint32_t save_flags = old_mem->placement; > - > - *old_mem = *mem; > + bo->mem = *mem; > mem->mm_node = NULL; > - ttm_flag_masked(&save_flags, mem->placement, > - TTM_PL_MASK_MEMTYPE); > goto moved; > } > > @@ -418,6 +419,7 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object > *bo, bool remove_all) > kref_put(&bo->list_kref, ttm_bo_ref_bug); > } > if (bo->mem.mm_node) { > + bo->mem.mm_node->private = NULL; > drm_mm_put_block(bo->mem.mm_node); > bo->mem.mm_node = NULL; > } > @@ -554,17 +556,14 @@ void ttm_bo_unref(struct ttm_buffer_object **p_bo) > } > EXPORT_SYMBOL(ttm_bo_unref); > > -static int ttm_bo_evict(struct ttm_buffer_object *bo, unsigned mem_type, > - bool interruptible, bool no_wait) > +static int ttm_bo_evict(struct ttm_buffer_object *bo, bool interruptible, > + bool no_wait) > { > - int ret = 0; > struct ttm_bo_device *bdev = bo->bdev; > struct ttm_bo_global *glob = bo->glob; > struct ttm_mem_reg evict_mem; > - uint32_t proposed_placement; > - > - if (bo->mem.mem_type != mem_type) > - goto out; > + struct ttm_placement placement; > + int ret = 0; > > spin_lock(&bo->lock); > ret = ttm_bo_wait(bo, false, interruptible, no_wait); > @@ -584,14 +583,9 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo, > unsigned mem_type, > evict_mem = bo->mem; > evict_mem.mm_node = NULL; > > - proposed_placement = bdev->driver->evict_flags(bo); > - > - ret = ttm_bo_mem_space(bo, proposed_placement, > - &evict_mem, interruptible, no_wait); > - if (unlikely(ret != 0 && ret != -ERESTART)) > - ret = ttm_bo_mem_space(bo, TTM_PL_FLAG_SYSTEM, > - &evict_mem, interruptible, no_wait); > - > + bdev->driver->evict_flags(bo, &placement); > + ret = ttm_bo_mem_space(bo, &placement, &evict_mem, interruptible, > + no_wait); > if (ret) { > if (ret != -ERESTART) > printk(KERN_ERR TTM_PFX > @@ -605,95 +599,117 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo, > unsigned mem_type, > if (ret) { > if (ret != -ERESTART) > printk(KERN_ERR TTM_PFX "Buffer eviction failed\n"); > + spin_lock(&glob->lru_lock); > + if (evict_mem.mm_node) { > + evict_mem.mm_node->private = NULL; > + drm_mm_put_block(evict_mem.mm_node); > + evict_mem.mm_node = NULL; > + } > + spin_unlock(&glob->lru_lock); > goto out; > } > + bo->evicted = true; > +out: > + return ret; > +} > + > +static int ttm_mem_evict_first(struct ttm_bo_device *bdev, > + uint32_t mem_type, > + bool interruptible, bool no_wait) > +{ > + struct ttm_bo_global *glob = bdev->glob; > + struct ttm_mem_type_manager *man = &bdev->man[mem_type]; > + struct ttm_buffer_object *bo; > + int ret, put_count = 0; > > spin_lock(&glob->lru_lock); > - if (evict_mem.mm_node) { > - drm_mm_put_block(evict_mem.mm_node); > - evict_mem.mm_node = NULL; > - } > + bo = list_first_entry(&man->lru, struct ttm_buffer_object, lru); > + kref_get(&bo->list_kref); > + ret = ttm_bo_reserve_locked(bo, interruptible, no_wait, false, 0); > + if (likely(ret == 0)) > + put_count = ttm_bo_del_from_lru(bo); > spin_unlock(&glob->lru_lock); > - bo->evicted = true; > -out: > + if (unlikely(ret != 0)) > + return ret; > + while (put_count--) > + kref_put(&bo->list_kref, ttm_bo_ref_bug); > + ret = ttm_bo_evict(bo, interruptible, no_wait); > + ttm_bo_unreserve(bo); > + kref_put(&bo->list_kref, ttm_bo_release_list); > return ret; > } > > +static int ttm_bo_man_get_node(struct ttm_buffer_object *bo, > + struct ttm_mem_type_manager *man, > + struct ttm_placement *placement, > + struct ttm_mem_reg *mem, > + struct drm_mm_node **node) > +{ > + struct ttm_bo_global *glob = bo->glob; > + unsigned long lpfn; > + int ret; > + > + lpfn = placement->lpfn; > + if (!lpfn) > + lpfn = man->size; > + *node = NULL; > + do { > + ret = drm_mm_pre_get(&man->manager); > + if (unlikely(ret)) > + return ret; > + > + spin_lock(&glob->lru_lock); > + *node = drm_mm_search_free_in_range(&man->manager, > + mem->num_pages, mem->page_alignment, > + placement->fpfn, lpfn, 1); > + if (unlikely(*node == NULL)) { > + spin_unlock(&glob->lru_lock); > + return 0; > + } > + *node = drm_mm_get_block_atomic_range(*node, mem->num_pages, > + mem->page_alignment, > + placement->fpfn, > + lpfn); > + spin_unlock(&glob->lru_lock); > + } while (*node == NULL); > + return 0; > +} > + > /** > * Repeatedly evict memory from the LRU for @mem_type until we create enough > * space, or we've evicted everything and there isn't enough space. > */ > -static int ttm_bo_mem_force_space(struct ttm_bo_device *bdev, > - struct ttm_mem_reg *mem, > - uint32_t mem_type, > - bool interruptible, bool no_wait) > +static int ttm_bo_mem_force_space(struct ttm_buffer_object *bo, > + uint32_t mem_type, > + struct ttm_placement *placement, > + struct ttm_mem_reg *mem, > + bool interruptible, bool no_wait) > { > + struct ttm_bo_device *bdev = bo->bdev; > struct ttm_bo_global *glob = bdev->glob; > - struct drm_mm_node *node; > - struct ttm_buffer_object *entry; > struct ttm_mem_type_manager *man = &bdev->man[mem_type]; > - struct list_head *lru; > - unsigned long num_pages = mem->num_pages; > - int put_count = 0; > + struct drm_mm_node *node; > int ret; > > -retry_pre_get: > - ret = drm_mm_pre_get(&man->manager); > - if (unlikely(ret != 0)) > - return ret; > - > - spin_lock(&glob->lru_lock); > do { > - node = drm_mm_search_free(&man->manager, num_pages, > - mem->page_alignment, 1); > + ret = ttm_bo_man_get_node(bo, man, placement, mem, &node); > + if (unlikely(ret != 0)) > + return ret; > if (node) > break; > - > - lru = &man->lru; > - if (list_empty(lru)) > + spin_lock(&glob->lru_lock); > + if (list_empty(&man->lru)) { > + spin_unlock(&glob->lru_lock); > break; > - > - entry = list_first_entry(lru, struct ttm_buffer_object, lru); > - kref_get(&entry->list_kref); > - > - ret = > - ttm_bo_reserve_locked(entry, interruptible, no_wait, > - false, 0); > - > - if (likely(ret == 0)) > - put_count = ttm_bo_del_from_lru(entry); > - > + } > spin_unlock(&glob->lru_lock); > - > + ret = ttm_mem_evict_first(bdev, mem_type, interruptible, > + no_wait); > if (unlikely(ret != 0)) > return ret; > - > - while (put_count--) > - kref_put(&entry->list_kref, ttm_bo_ref_bug); > - > - ret = ttm_bo_evict(entry, mem_type, interruptible, no_wait); > - > - ttm_bo_unreserve(entry); > - > - kref_put(&entry->list_kref, ttm_bo_release_list); > - if (ret) > - return ret; > - > - spin_lock(&glob->lru_lock); > } while (1); > - > - if (!node) { > - spin_unlock(&glob->lru_lock); > + if (node == NULL) > return -ENOMEM; > - } > - > - node = drm_mm_get_block_atomic(node, num_pages, mem->page_alignment); > - if (unlikely(!node)) { > - spin_unlock(&glob->lru_lock); > - goto retry_pre_get; > - } > - > - spin_unlock(&glob->lru_lock); > mem->mm_node = node; > mem->mem_type = mem_type; > return 0; > @@ -724,7 +740,6 @@ static uint32_t ttm_bo_select_caching(struct > ttm_mem_type_manager *man, > return result; > } > > - > static bool ttm_bo_mt_compatible(struct ttm_mem_type_manager *man, > bool disallow_fixed, > uint32_t mem_type, > @@ -748,6 +763,18 @@ static bool ttm_bo_mt_compatible(struct > ttm_mem_type_manager *man, > return true; > } > > +static inline int ttm_mem_type_from_flags(uint32_t flags, uint32_t *mem_type) > +{ > + int i; > + > + for (i = 0; i <= TTM_PL_PRIV5; i++) > + if (flags & (1 << i)) { > + *mem_type = i; > + return 0; > + } > + return -EINVAL; > +} > + > /** > * Creates space for memory region @mem according to its type. > * > @@ -757,66 +784,55 @@ static bool ttm_bo_mt_compatible(struct > ttm_mem_type_manager *man, > * space. > */ > int ttm_bo_mem_space(struct ttm_buffer_object *bo, > - uint32_t proposed_placement, > - struct ttm_mem_reg *mem, > - bool interruptible, bool no_wait) > + struct ttm_placement *placement, > + struct ttm_mem_reg *mem, > + bool interruptible, bool no_wait) > { > struct ttm_bo_device *bdev = bo->bdev; > - struct ttm_bo_global *glob = bo->glob; > struct ttm_mem_type_manager *man; > - > - uint32_t num_prios = bdev->driver->num_mem_type_prio; > - const uint32_t *prios = bdev->driver->mem_type_prio; > - uint32_t i; > uint32_t mem_type = TTM_PL_SYSTEM; > uint32_t cur_flags = 0; > bool type_found = false; > bool type_ok = false; > bool has_eagain = false; > struct drm_mm_node *node = NULL; > - int ret; > + int i, ret; > > mem->mm_node = NULL; > - for (i = 0; i < num_prios; ++i) { > - mem_type = prios[i]; > + for (i = 0; i <= placement->num_placement; ++i) { > + ret = ttm_mem_type_from_flags(placement->placement[i], > + &mem_type); > + if (ret) > + return ret; > man = &bdev->man[mem_type]; > > type_ok = ttm_bo_mt_compatible(man, > - bo->type == ttm_bo_type_user, > - mem_type, proposed_placement, > - &cur_flags); > + bo->type == ttm_bo_type_user, > + mem_type, > + placement->placement[i], > + &cur_flags); > > if (!type_ok) > continue; > > cur_flags = ttm_bo_select_caching(man, bo->mem.placement, > cur_flags); > + /* > + * Use the access and other non-mapping-related flag bits from > + * the memory placement flags to the current flags > + */ > + ttm_flag_masked(&cur_flags, placement->placement[i], > + ~TTM_PL_MASK_MEMTYPE); > > if (mem_type == TTM_PL_SYSTEM) > break; > > if (man->has_type && man->use_type) { > type_found = true; > - do { > - ret = drm_mm_pre_get(&man->manager); > - if (unlikely(ret)) > - return ret; > - > - spin_lock(&glob->lru_lock); > - node = drm_mm_search_free(&man->manager, > - mem->num_pages, > - mem->page_alignment, > - 1); > - if (unlikely(!node)) { > - spin_unlock(&glob->lru_lock); > - break; > - } > - node = drm_mm_get_block_atomic(node, > - mem->num_pages, > - mem-> > - page_alignment); > - spin_unlock(&glob->lru_lock); > - } while (!node); > + ret = ttm_bo_man_get_node(bo, man, placement, mem, > + &node); > + if (unlikely(ret)) > + return ret; > } > if (node) > break; > @@ -826,43 +842,48 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo, > mem->mm_node = node; > mem->mem_type = mem_type; > mem->placement = cur_flags; > + if (node) > + node->private = bo; > return 0; > } > > if (!type_found) > return -EINVAL; > > - num_prios = bdev->driver->num_mem_busy_prio; > - prios = bdev->driver->mem_busy_prio; > - > - for (i = 0; i < num_prios; ++i) { > - mem_type = prios[i]; > + for (i = 0; i <= placement->num_busy_placement; ++i) { > + ret = ttm_mem_type_from_flags(placement->placement[i], > + &mem_type); > + if (ret) > + return ret; > man = &bdev->man[mem_type]; > - > if (!man->has_type) > continue; > - > if (!ttm_bo_mt_compatible(man, > - bo->type == ttm_bo_type_user, > - mem_type, > - proposed_placement, &cur_flags)) > + bo->type == ttm_bo_type_user, > + mem_type, > + placement->placement[i], > + &cur_flags)) > continue; > > cur_flags = ttm_bo_select_caching(man, bo->mem.placement, > cur_flags); > + /* > + * Use the access and other non-mapping-related flag bits from > + * the memory placement flags to the current flags > + */ > + ttm_flag_masked(&cur_flags, placement->placement[i], > + ~TTM_PL_MASK_MEMTYPE); > > - ret = ttm_bo_mem_force_space(bdev, mem, mem_type, > - interruptible, no_wait); > - > + ret = ttm_bo_mem_force_space(bo, mem_type, placement, mem, > + interruptible, no_wait); > if (ret == 0 && mem->mm_node) { > mem->placement = cur_flags; > + mem->mm_node->private = bo; > return 0; > } > - > if (ret == -ERESTART) > has_eagain = true; > } > - > ret = (has_eagain) ? -ERESTART : -ENOMEM; > return ret; > } > @@ -885,8 +906,8 @@ int ttm_bo_wait_cpu(struct ttm_buffer_object *bo, bool > no_wait) > } > > int ttm_bo_move_buffer(struct ttm_buffer_object *bo, > - uint32_t proposed_placement, > - bool interruptible, bool no_wait) > + struct ttm_placement *placement, > + bool interruptible, bool no_wait) > { > struct ttm_bo_global *glob = bo->glob; > int ret = 0; > @@ -899,101 +920,82 @@ int ttm_bo_move_buffer(struct ttm_buffer_object *bo, > * Have the driver move function wait for idle when necessary, > * instead of doing it here. > */ > - > spin_lock(&bo->lock); > ret = ttm_bo_wait(bo, false, interruptible, no_wait); > spin_unlock(&bo->lock); > - > if (ret) > return ret; > - > mem.num_pages = bo->num_pages; > mem.size = mem.num_pages << PAGE_SHIFT; > mem.page_alignment = bo->mem.page_alignment; > - > /* > * Determine where to move the buffer. > */ > - > - ret = ttm_bo_mem_space(bo, proposed_placement, &mem, > - interruptible, no_wait); > + ret = ttm_bo_mem_space(bo, placement, &mem, interruptible, no_wait); > if (ret) > goto out_unlock; > - > ret = ttm_bo_handle_move_mem(bo, &mem, false, interruptible, no_wait); > - > out_unlock: > if (ret && mem.mm_node) { > spin_lock(&glob->lru_lock); > + mem.mm_node->private = NULL; > drm_mm_put_block(mem.mm_node); > spin_unlock(&glob->lru_lock); > } > return ret; > } > > -static int ttm_bo_mem_compat(uint32_t proposed_placement, > +static int ttm_bo_mem_compat(struct ttm_placement *placement, > struct ttm_mem_reg *mem) > { > - if ((proposed_placement & mem->placement & TTM_PL_MASK_MEM) == 0) > - return 0; > - if ((proposed_placement & mem->placement & TTM_PL_MASK_CACHING) == 0) > - return 0; > - > - return 1; > + int i; > + > + for (i = 0; i < placement->num_placement; i++) { > + if ((placement->placement[i] & mem->placement & > + TTM_PL_MASK_CACHING) && > + (placement->placement[i] & mem->placement & > + TTM_PL_MASK_MEM)) > + return i; > + } > + return -1; > } > > int ttm_buffer_object_validate(struct ttm_buffer_object *bo, > - uint32_t proposed_placement, > - bool interruptible, bool no_wait) > + struct ttm_placement *placement, > + bool interruptible, bool no_wait) > { > int ret; > > BUG_ON(!atomic_read(&bo->reserved)); > - bo->proposed_placement = proposed_placement; > - > - TTM_DEBUG("Proposed placement 0x%08lx, Old flags 0x%08lx\n", > - (unsigned long)proposed_placement, > - (unsigned long)bo->mem.placement); > - > + /* Check that range is valid */ > + if (placement->lpfn || placement->fpfn) > + if (placement->fpfn > placement->lpfn || > + (placement->lpfn - placement->fpfn) < bo->num_pages) > + return -EINVAL; > /* > * Check whether we need to move buffer. > */ > - > - if (!ttm_bo_mem_compat(bo->proposed_placement, &bo->mem)) { > - ret = ttm_bo_move_buffer(bo, bo->proposed_placement, > - interruptible, no_wait); > - if (ret) { > - if (ret != -ERESTART) > - printk(KERN_ERR TTM_PFX > - "Failed moving buffer. " > - "Proposed placement 0x%08x\n", > - bo->proposed_placement); > - if (ret == -ENOMEM) > - printk(KERN_ERR TTM_PFX > - "Out of aperture space or " > - "DRM memory quota.\n"); > + ret = ttm_bo_mem_compat(placement, &bo->mem); > + if (ret < 0) { > + ret = ttm_bo_move_buffer(bo, placement, interruptible, no_wait); > + if (ret) > return ret; > - } > + } else { > + /* > + * Use the access and other non-mapping-related flag bits from > + * the compatible memory placement flags to the active flags > + */ > + ttm_flag_masked(&bo->mem.placement, placement->placement[ret], > + ~TTM_PL_MASK_MEMTYPE); > } > - > /* > * We might need to add a TTM. > */ > - > if (bo->mem.mem_type == TTM_PL_SYSTEM && bo->ttm == NULL) { > ret = ttm_bo_add_ttm(bo, true); > if (ret) > return ret; > } > - /* > - * Validation has succeeded, move the access and other > - * non-mapping-related flag bits from the proposed flags to > - * the active flags > - */ > - > - ttm_flag_masked(&bo->mem.placement, bo->proposed_placement, > - ~TTM_PL_MASK_MEMTYPE); > - > return 0; > } > EXPORT_SYMBOL(ttm_buffer_object_validate); > @@ -1041,8 +1043,10 @@ int ttm_buffer_object_init(struct ttm_bo_device *bdev, > size_t acc_size, > void (*destroy) (struct ttm_buffer_object *)) > { > - int ret = 0; > + int i, c, ret = 0; > unsigned long num_pages; > + uint32_t placements[8]; > + struct ttm_placement placement; > > size += buffer_start & ~PAGE_MASK; > num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; > @@ -1099,7 +1103,16 @@ int ttm_buffer_object_init(struct ttm_bo_device *bdev, > goto out_err; > } > > - ret = ttm_buffer_object_validate(bo, flags, interruptible, false); > + placement.fpfn = 0; > + placement.lpfn = 0; > + for (i = 0, c = 0; i <= TTM_PL_PRIV5; i++) > + if (flags & (1 << i)) > + placements[c++] = (flags & ~TTM_PL_MASK_MEM) | (1 << i); > + placement.placement = placements; > + placement.num_placement = c; > + placement.busy_placement = placements; > + placement.num_busy_placement = c; > + ret = ttm_buffer_object_validate(bo, &placement, interruptible, false); > if (ret) > goto out_err; > > @@ -1134,8 +1147,8 @@ int ttm_buffer_object_create(struct ttm_bo_device *bdev, > struct ttm_buffer_object **p_bo) > { > struct ttm_buffer_object *bo; > - int ret; > struct ttm_mem_global *mem_glob = bdev->glob->mem_glob; > + int ret; > > size_t acc_size = > ttm_bo_size(bdev->glob, (size + PAGE_SIZE - 1) >> PAGE_SHIFT); > @@ -1160,66 +1173,32 @@ int ttm_buffer_object_create(struct ttm_bo_device > *bdev, > return ret; > } > > -static int ttm_bo_leave_list(struct ttm_buffer_object *bo, > - uint32_t mem_type, bool allow_errors) > -{ > - int ret; > - > - spin_lock(&bo->lock); > - ret = ttm_bo_wait(bo, false, false, false); > - spin_unlock(&bo->lock); > - > - if (ret && allow_errors) > - goto out; > - > - if (bo->mem.mem_type == mem_type) > - ret = ttm_bo_evict(bo, mem_type, false, false); > - > - if (ret) { > - if (allow_errors) { > - goto out; > - } else { > - ret = 0; > - printk(KERN_ERR TTM_PFX "Cleanup eviction failed\n"); > - } > - } > - > -out: > - return ret; > -} > - > static int ttm_bo_force_list_clean(struct ttm_bo_device *bdev, > - struct list_head *head, > - unsigned mem_type, bool allow_errors) > + unsigned mem_type, bool allow_errors) > { > + struct ttm_mem_type_manager *man = &bdev->man[mem_type]; > struct ttm_bo_global *glob = bdev->glob; > - struct ttm_buffer_object *entry; > int ret; > - int put_count; > > /* > * Can't use standard list traversal since we're unlocking. > */ > > spin_lock(&glob->lru_lock); > - > - while (!list_empty(head)) { > - entry = list_first_entry(head, struct ttm_buffer_object, lru); > - kref_get(&entry->list_kref); > - ret = ttm_bo_reserve_locked(entry, false, false, false, 0); > - put_count = ttm_bo_del_from_lru(entry); > + while (!list_empty(&man->lru)) { > spin_unlock(&glob->lru_lock); > - while (put_count--) > - kref_put(&entry->list_kref, ttm_bo_ref_bug); > - BUG_ON(ret); > - ret = ttm_bo_leave_list(entry, mem_type, allow_errors); > - ttm_bo_unreserve(entry); > - kref_put(&entry->list_kref, ttm_bo_release_list); > + ret = ttm_mem_evict_first(bdev, mem_type, false, false); > + if (ret) { > + if (allow_errors) { > + return ret; > + } else { > + printk(KERN_ERR TTM_PFX > + "Cleanup eviction failed\n"); > + } > + } > spin_lock(&glob->lru_lock); > } > - > spin_unlock(&glob->lru_lock); > - > return 0; > } > > @@ -1246,7 +1225,7 @@ int ttm_bo_clean_mm(struct ttm_bo_device *bdev, > unsigned mem_type) > > ret = 0; > if (mem_type > 0) { > - ttm_bo_force_list_clean(bdev, &man->lru, mem_type, false); > + ttm_bo_force_list_clean(bdev, mem_type, false); > > spin_lock(&glob->lru_lock); > if (drm_mm_clean(&man->manager)) > @@ -1279,12 +1258,12 @@ int ttm_bo_evict_mm(struct ttm_bo_device *bdev, > unsigned mem_type) > return 0; > } > > - return ttm_bo_force_list_clean(bdev, &man->lru, mem_type, true); > + return ttm_bo_force_list_clean(bdev, mem_type, true); > } > EXPORT_SYMBOL(ttm_bo_evict_mm); > > int ttm_bo_init_mm(struct ttm_bo_device *bdev, unsigned type, > - unsigned long p_offset, unsigned long p_size) > + unsigned long p_size) > { > int ret = -EINVAL; > struct ttm_mem_type_manager *man; > @@ -1314,7 +1293,7 @@ int ttm_bo_init_mm(struct ttm_bo_device *bdev, unsigned > type, > type); > return ret; > } > - ret = drm_mm_init(&man->manager, p_offset, p_size); > + ret = drm_mm_init(&man->manager, 0, p_size); > if (ret) > return ret; > } > @@ -1463,7 +1442,7 @@ int ttm_bo_device_init(struct ttm_bo_device *bdev, > * Initialize the system memory buffer type. > * Other types need to be driver / IOCTL initialized. > */ > - ret = ttm_bo_init_mm(bdev, TTM_PL_SYSTEM, 0, 0); > + ret = ttm_bo_init_mm(bdev, TTM_PL_SYSTEM, 0); > if (unlikely(ret != 0)) > goto out_no_sys; > > diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h > index 4911461..2f7f56d 100644 > --- a/include/drm/ttm/ttm_bo_api.h > +++ b/include/drm/ttm/ttm_bo_api.h > @@ -44,6 +44,29 @@ struct ttm_bo_device; > > struct drm_mm_node; > > + > +/** > + * struct ttm_placement > + * > + * @fpfn: first valid page frame number to put the object > + * @lpfn: last valid page frame number to put the object > + * @num_placement: number of prefered placements > + * @placement: prefered placements > + * @num_busy_placement: number of prefered placements when need to > evict buffer > + * @busy_placement: prefered placements when need to evict buffer > + * > + * Structure indicating the placement you request for an object. > + */ > +struct ttm_placement { > + unsigned fpfn; > + unsigned lpfn; > + unsigned num_placement; > + const uint32_t *placement; > + unsigned num_busy_placement; > + const uint32_t *busy_placement; > +}; > + > + > /** > * struct ttm_mem_reg > * > @@ -109,10 +132,6 @@ struct ttm_tt; > * the object is destroyed. > * @event_queue: Queue for processes waiting on buffer object status change. > * @lock: spinlock protecting mostly synchronization members. > - * @proposed_placement: Proposed placement for the buffer. Changed only by > the > - * creator prior to validation as opposed to bo->mem.proposed_flags which is > - * changed by the implementation prior to a buffer move if it wants to > outsmart > - * the buffer creator / user. This latter happens, for example, at eviction. > * @mem: structure describing current placement. > * @persistant_swap_storage: Usually the swap storage is deleted for buffers > * pinned in physical memory. If this behaviour is not desired, this member > @@ -177,7 +196,6 @@ struct ttm_buffer_object { > * Members protected by the bo::reserved lock. > */ > > - uint32_t proposed_placement; > struct ttm_mem_reg mem; > struct file *persistant_swap_storage; > struct ttm_tt *ttm; > @@ -293,21 +311,22 @@ extern int ttm_bo_wait(struct ttm_buffer_object *bo, > bool lazy, > * ttm_buffer_object_validate > * > * @bo: The buffer object. > - * @proposed_placement: Proposed_placement for the buffer object. > + * @placement: Proposed placement for the buffer object. > * @interruptible: Sleep interruptible if sleeping. > * @no_wait: Return immediately if the buffer is busy. > * > * Changes placement and caching policy of the buffer object > - * according to bo::proposed_flags. > + * according proposed placement. > * Returns > - * -EINVAL on invalid proposed_flags. > + * -EINVAL on invalid proposed placement. > * -ENOMEM on out-of-memory condition. > * -EBUSY if no_wait is true and buffer busy. > * -ERESTART if interrupted by a signal. > */ > extern int ttm_buffer_object_validate(struct ttm_buffer_object *bo, > - uint32_t proposed_placement, > - bool interruptible, bool no_wait); > + struct ttm_placement *placement, > + bool interruptible, bool no_wait); > + > /** > * ttm_bo_unref > * > @@ -445,7 +464,6 @@ extern int ttm_bo_check_placement(struct > ttm_buffer_object *bo, > * > * @bdev: Pointer to a ttm_bo_device struct. > * @mem_type: The memory type. > - * @p_offset: offset for managed area in pages. > * @p_size: size managed area in pages. > * > * Initialize a manager for a given memory type. > @@ -458,7 +476,7 @@ extern int ttm_bo_check_placement(struct > ttm_buffer_object *bo, > */ > > extern int ttm_bo_init_mm(struct ttm_bo_device *bdev, unsigned type, > - unsigned long p_offset, unsigned long p_size); > + unsigned long p_size); > /** > * ttm_bo_clean_mm > * > diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h > index e8cd6d2..1dd1dbc 100644 > --- a/include/drm/ttm/ttm_bo_driver.h > +++ b/include/drm/ttm/ttm_bo_driver.h > @@ -242,12 +242,6 @@ struct ttm_mem_type_manager { > /** > * struct ttm_bo_driver > * > - * @mem_type_prio: Priority array of memory types to place a buffer object in > - * if it fits without evicting buffers from any of these memory types. > - * @mem_busy_prio: Priority array of memory types to place a buffer object in > - * if it needs to evict buffers to make room. > - * @num_mem_type_prio: Number of elements in the @mem_type_prio array. > - * @num_mem_busy_prio: Number of elements in the @num_mem_busy_prio array. > * @create_ttm_backend_entry: Callback to create a struct ttm_backend. > * @invalidate_caches: Callback to invalidate read caches when a buffer > object > * has been evicted. > @@ -265,11 +259,6 @@ struct ttm_mem_type_manager { > */ > > struct ttm_bo_driver { > - const uint32_t *mem_type_prio; > - const uint32_t *mem_busy_prio; > - uint32_t num_mem_type_prio; > - uint32_t num_mem_busy_prio; > - > /** > * struct ttm_bo_driver member create_ttm_backend_entry > * > @@ -306,7 +295,8 @@ struct ttm_bo_driver { > * finished, they'll end up in bo->mem.flags > */ > > - uint32_t(*evict_flags) (struct ttm_buffer_object *bo); > + void(*evict_flags) (struct ttm_buffer_object *bo, > + struct ttm_placement *placement); > /** > * struct ttm_bo_driver member move: > * > @@ -642,9 +632,9 @@ extern bool ttm_mem_reg_is_pci(struct ttm_bo_device *bdev, > * -ERESTART: An interruptible sleep was interrupted by a signal. > */ > extern int ttm_bo_mem_space(struct ttm_buffer_object *bo, > - uint32_t proposed_placement, > - struct ttm_mem_reg *mem, > - bool interruptible, bool no_wait); > + struct ttm_placement *placement, > + struct ttm_mem_reg *mem, > + bool interruptible, bool no_wait); > /** > * ttm_bo_wait_for_cpu > * ------------------------------------------------------------------------------ Return on Information: Google Enterprise Search pays you back Get the facts. http://p.sf.net/sfu/google-dev2dev -- _______________________________________________ Dri-devel mailing list Dri-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/dri-devel