Loading drivers/gpu/drm/nouveau/nouveau_mem.c +10 −16 Original line number Diff line number Diff line Loading @@ -742,30 +742,24 @@ nouveau_vram_manager_debug(struct ttm_mem_type_manager *man, const char *prefix) { struct nouveau_mm *mm = man->priv; struct nouveau_mm_node *r; u64 total = 0, ttotal[3] = {}, tused[3] = {}, tfree[3] = {}; int i; u32 total = 0, free = 0; mutex_lock(&mm->mutex); list_for_each_entry(r, &mm->nodes, nl_entry) { printk(KERN_DEBUG "%s %s-%d: 0x%010llx 0x%010llx\n", prefix, r->free ? "free" : "used", r->type, ((u64)r->offset << 12), printk(KERN_DEBUG "%s %d: 0x%010llx 0x%010llx\n", prefix, r->type, ((u64)r->offset << 12), (((u64)r->offset + r->length) << 12)); total += r->length; ttotal[r->type] += r->length; if (r->free) tfree[r->type] += r->length; else tused[r->type] += r->length; if (!r->type) free += r->length; } mutex_unlock(&mm->mutex); printk(KERN_DEBUG "%s total: 0x%010llx\n", prefix, total << 12); for (i = 0; i < 3; i++) { printk(KERN_DEBUG "%s type %d: 0x%010llx, " "used 0x%010llx, free 0x%010llx\n", prefix, i, ttotal[i] << 12, tused[i] << 12, tfree[i] << 12); } printk(KERN_DEBUG "%s total: 0x%010llx free: 0x%010llx\n", prefix, (u64)total << 12, (u64)free << 12); printk(KERN_DEBUG "%s block: 0x%08x\n", prefix, mm->block_size << 12); } const struct ttm_mem_type_manager_func nouveau_vram_manager = { Loading drivers/gpu/drm/nouveau/nouveau_mm.c +41 −141 Original line number Diff line number Diff line Loading @@ -48,175 +48,76 @@ region_split(struct nouveau_mm *rmm, struct nouveau_mm_node *a, u32 size) b->offset = a->offset; b->length = size; b->free = a->free; b->type = a->type; a->offset += size; a->length -= size; list_add_tail(&b->nl_entry, &a->nl_entry); if (b->free) if (b->type == 0) list_add_tail(&b->fl_entry, &a->fl_entry); return b; } static struct nouveau_mm_node * nouveau_mm_merge(struct nouveau_mm *rmm, struct nouveau_mm_node *this) #define node(root, dir) ((root)->nl_entry.dir == &rmm->nodes) ? NULL : \ list_entry((root)->nl_entry.dir, struct nouveau_mm_node, nl_entry) void nouveau_mm_put(struct nouveau_mm *rmm, struct nouveau_mm_node *this) { struct nouveau_mm_node *prev, *next; struct nouveau_mm_node *prev = node(this, prev); struct nouveau_mm_node *next = node(this, next); /* try to merge with free adjacent entries of same type */ prev = list_entry(this->nl_entry.prev, struct nouveau_mm_node, nl_entry); if (this->nl_entry.prev != &rmm->nodes) { if (prev->free && prev->type == this->type) { list_add(&this->fl_entry, &rmm->free); this->type = 0; if (prev && prev->type == 0) { prev->length += this->length; region_put(rmm, this); this = prev; } } next = list_entry(this->nl_entry.next, struct nouveau_mm_node, nl_entry); if (this->nl_entry.next != &rmm->nodes) { if (next->free && next->type == this->type) { if (next && next->type == 0) { next->offset = this->offset; next->length += this->length; region_put(rmm, this); this = next; } } return this; } void nouveau_mm_put(struct nouveau_mm *rmm, struct nouveau_mm_node *this) { u32 block_s, block_l; this->free = true; list_add(&this->fl_entry, &rmm->free); this = nouveau_mm_merge(rmm, this); /* any entirely free blocks now? we'll want to remove typing * on them now so they can be use for any memory allocation */ block_s = roundup(this->offset, rmm->block_size); if (block_s + rmm->block_size > this->offset + this->length) return; /* split off any still-typed region at the start */ if (block_s != this->offset) { if (!region_split(rmm, this, block_s - this->offset)) return; } /* split off the soon-to-be-untyped block(s) */ block_l = rounddown(this->length, rmm->block_size); if (block_l != this->length) { this = region_split(rmm, this, block_l); if (!this) return; } /* mark as having no type, and retry merge with any adjacent * untyped blocks */ this->type = 0; nouveau_mm_merge(rmm, this); } int nouveau_mm_get(struct nouveau_mm *rmm, int type, u32 size, u32 size_nc, u32 align, struct nouveau_mm_node **pnode) { struct nouveau_mm_node *this, *tmp, *next; u32 splitoff, avail, alloc; list_for_each_entry_safe(this, tmp, &rmm->free, fl_entry) { next = list_entry(this->nl_entry.next, struct nouveau_mm_node, nl_entry); if (this->nl_entry.next == &rmm->nodes) next = NULL; /* skip wrongly typed blocks */ if (this->type && this->type != type) struct nouveau_mm_node *prev, *this, *next; u32 min = size_nc ? size_nc : size; u32 align_mask = align - 1; u32 splitoff; u32 s, e; list_for_each_entry(this, &rmm->free, fl_entry) { e = this->offset + this->length; s = this->offset; prev = node(this, prev); if (prev && prev->type != type) s = roundup(s, rmm->block_size); next = node(this, next); if (next && next->type != type) e = rounddown(e, rmm->block_size); s = (s + align_mask) & ~align_mask; e &= ~align_mask; if (s > e || e - s < min) continue; /* account for alignment */ splitoff = this->offset & (align - 1); if (splitoff) splitoff = align - splitoff; if (this->length <= splitoff) continue; /* determine total memory available from this, and * the next block (if appropriate) */ avail = this->length; if (next && next->free && (!next->type || next->type == type)) avail += next->length; avail -= splitoff; /* determine allocation size */ if (size_nc) { alloc = min(avail, size); alloc = rounddown(alloc, size_nc); if (alloc == 0) continue; } else { alloc = size; if (avail < alloc) continue; } /* untyped block, split off a chunk that's a multiple * of block_size and type it */ if (!this->type) { u32 block = roundup(alloc + splitoff, rmm->block_size); if (this->length < block) continue; splitoff = s - this->offset; if (splitoff && !region_split(rmm, this, splitoff)) return -ENOMEM; this = region_split(rmm, this, block); this = region_split(rmm, this, min(size, e - s)); if (!this) return -ENOMEM; this->type = type; } /* stealing memory from adjacent block */ if (alloc > this->length) { u32 amount = alloc - (this->length - splitoff); if (!next->type) { amount = roundup(amount, rmm->block_size); next = region_split(rmm, next, amount); if (!next) return -ENOMEM; next->type = type; } this->length += amount; next->offset += amount; next->length -= amount; if (!next->length) { list_del(&next->nl_entry); list_del(&next->fl_entry); kfree(next); } } if (splitoff) { if (!region_split(rmm, this, splitoff)) return -ENOMEM; } this = region_split(rmm, this, alloc); if (this == NULL) return -ENOMEM; this->free = false; list_del(&this->fl_entry); *pnode = this; return 0; Loading @@ -234,7 +135,6 @@ nouveau_mm_init(struct nouveau_mm **prmm, u32 offset, u32 length, u32 block) heap = kzalloc(sizeof(*heap), GFP_KERNEL); if (!heap) return -ENOMEM; heap->free = true; heap->offset = roundup(offset, block); heap->length = rounddown(offset + length, block) - heap->offset; Loading drivers/gpu/drm/nouveau/nouveau_mm.h +1 −3 Original line number Diff line number Diff line Loading @@ -30,9 +30,7 @@ struct nouveau_mm_node { struct list_head fl_entry; struct list_head rl_entry; bool free; int type; u8 type; u32 offset; u32 length; }; Loading Loading
drivers/gpu/drm/nouveau/nouveau_mem.c +10 −16 Original line number Diff line number Diff line Loading @@ -742,30 +742,24 @@ nouveau_vram_manager_debug(struct ttm_mem_type_manager *man, const char *prefix) { struct nouveau_mm *mm = man->priv; struct nouveau_mm_node *r; u64 total = 0, ttotal[3] = {}, tused[3] = {}, tfree[3] = {}; int i; u32 total = 0, free = 0; mutex_lock(&mm->mutex); list_for_each_entry(r, &mm->nodes, nl_entry) { printk(KERN_DEBUG "%s %s-%d: 0x%010llx 0x%010llx\n", prefix, r->free ? "free" : "used", r->type, ((u64)r->offset << 12), printk(KERN_DEBUG "%s %d: 0x%010llx 0x%010llx\n", prefix, r->type, ((u64)r->offset << 12), (((u64)r->offset + r->length) << 12)); total += r->length; ttotal[r->type] += r->length; if (r->free) tfree[r->type] += r->length; else tused[r->type] += r->length; if (!r->type) free += r->length; } mutex_unlock(&mm->mutex); printk(KERN_DEBUG "%s total: 0x%010llx\n", prefix, total << 12); for (i = 0; i < 3; i++) { printk(KERN_DEBUG "%s type %d: 0x%010llx, " "used 0x%010llx, free 0x%010llx\n", prefix, i, ttotal[i] << 12, tused[i] << 12, tfree[i] << 12); } printk(KERN_DEBUG "%s total: 0x%010llx free: 0x%010llx\n", prefix, (u64)total << 12, (u64)free << 12); printk(KERN_DEBUG "%s block: 0x%08x\n", prefix, mm->block_size << 12); } const struct ttm_mem_type_manager_func nouveau_vram_manager = { Loading
drivers/gpu/drm/nouveau/nouveau_mm.c +41 −141 Original line number Diff line number Diff line Loading @@ -48,175 +48,76 @@ region_split(struct nouveau_mm *rmm, struct nouveau_mm_node *a, u32 size) b->offset = a->offset; b->length = size; b->free = a->free; b->type = a->type; a->offset += size; a->length -= size; list_add_tail(&b->nl_entry, &a->nl_entry); if (b->free) if (b->type == 0) list_add_tail(&b->fl_entry, &a->fl_entry); return b; } static struct nouveau_mm_node * nouveau_mm_merge(struct nouveau_mm *rmm, struct nouveau_mm_node *this) #define node(root, dir) ((root)->nl_entry.dir == &rmm->nodes) ? NULL : \ list_entry((root)->nl_entry.dir, struct nouveau_mm_node, nl_entry) void nouveau_mm_put(struct nouveau_mm *rmm, struct nouveau_mm_node *this) { struct nouveau_mm_node *prev, *next; struct nouveau_mm_node *prev = node(this, prev); struct nouveau_mm_node *next = node(this, next); /* try to merge with free adjacent entries of same type */ prev = list_entry(this->nl_entry.prev, struct nouveau_mm_node, nl_entry); if (this->nl_entry.prev != &rmm->nodes) { if (prev->free && prev->type == this->type) { list_add(&this->fl_entry, &rmm->free); this->type = 0; if (prev && prev->type == 0) { prev->length += this->length; region_put(rmm, this); this = prev; } } next = list_entry(this->nl_entry.next, struct nouveau_mm_node, nl_entry); if (this->nl_entry.next != &rmm->nodes) { if (next->free && next->type == this->type) { if (next && next->type == 0) { next->offset = this->offset; next->length += this->length; region_put(rmm, this); this = next; } } return this; } void nouveau_mm_put(struct nouveau_mm *rmm, struct nouveau_mm_node *this) { u32 block_s, block_l; this->free = true; list_add(&this->fl_entry, &rmm->free); this = nouveau_mm_merge(rmm, this); /* any entirely free blocks now? we'll want to remove typing * on them now so they can be use for any memory allocation */ block_s = roundup(this->offset, rmm->block_size); if (block_s + rmm->block_size > this->offset + this->length) return; /* split off any still-typed region at the start */ if (block_s != this->offset) { if (!region_split(rmm, this, block_s - this->offset)) return; } /* split off the soon-to-be-untyped block(s) */ block_l = rounddown(this->length, rmm->block_size); if (block_l != this->length) { this = region_split(rmm, this, block_l); if (!this) return; } /* mark as having no type, and retry merge with any adjacent * untyped blocks */ this->type = 0; nouveau_mm_merge(rmm, this); } int nouveau_mm_get(struct nouveau_mm *rmm, int type, u32 size, u32 size_nc, u32 align, struct nouveau_mm_node **pnode) { struct nouveau_mm_node *this, *tmp, *next; u32 splitoff, avail, alloc; list_for_each_entry_safe(this, tmp, &rmm->free, fl_entry) { next = list_entry(this->nl_entry.next, struct nouveau_mm_node, nl_entry); if (this->nl_entry.next == &rmm->nodes) next = NULL; /* skip wrongly typed blocks */ if (this->type && this->type != type) struct nouveau_mm_node *prev, *this, *next; u32 min = size_nc ? size_nc : size; u32 align_mask = align - 1; u32 splitoff; u32 s, e; list_for_each_entry(this, &rmm->free, fl_entry) { e = this->offset + this->length; s = this->offset; prev = node(this, prev); if (prev && prev->type != type) s = roundup(s, rmm->block_size); next = node(this, next); if (next && next->type != type) e = rounddown(e, rmm->block_size); s = (s + align_mask) & ~align_mask; e &= ~align_mask; if (s > e || e - s < min) continue; /* account for alignment */ splitoff = this->offset & (align - 1); if (splitoff) splitoff = align - splitoff; if (this->length <= splitoff) continue; /* determine total memory available from this, and * the next block (if appropriate) */ avail = this->length; if (next && next->free && (!next->type || next->type == type)) avail += next->length; avail -= splitoff; /* determine allocation size */ if (size_nc) { alloc = min(avail, size); alloc = rounddown(alloc, size_nc); if (alloc == 0) continue; } else { alloc = size; if (avail < alloc) continue; } /* untyped block, split off a chunk that's a multiple * of block_size and type it */ if (!this->type) { u32 block = roundup(alloc + splitoff, rmm->block_size); if (this->length < block) continue; splitoff = s - this->offset; if (splitoff && !region_split(rmm, this, splitoff)) return -ENOMEM; this = region_split(rmm, this, block); this = region_split(rmm, this, min(size, e - s)); if (!this) return -ENOMEM; this->type = type; } /* stealing memory from adjacent block */ if (alloc > this->length) { u32 amount = alloc - (this->length - splitoff); if (!next->type) { amount = roundup(amount, rmm->block_size); next = region_split(rmm, next, amount); if (!next) return -ENOMEM; next->type = type; } this->length += amount; next->offset += amount; next->length -= amount; if (!next->length) { list_del(&next->nl_entry); list_del(&next->fl_entry); kfree(next); } } if (splitoff) { if (!region_split(rmm, this, splitoff)) return -ENOMEM; } this = region_split(rmm, this, alloc); if (this == NULL) return -ENOMEM; this->free = false; list_del(&this->fl_entry); *pnode = this; return 0; Loading @@ -234,7 +135,6 @@ nouveau_mm_init(struct nouveau_mm **prmm, u32 offset, u32 length, u32 block) heap = kzalloc(sizeof(*heap), GFP_KERNEL); if (!heap) return -ENOMEM; heap->free = true; heap->offset = roundup(offset, block); heap->length = rounddown(offset + length, block) - heap->offset; Loading
drivers/gpu/drm/nouveau/nouveau_mm.h +1 −3 Original line number Diff line number Diff line Loading @@ -30,9 +30,7 @@ struct nouveau_mm_node { struct list_head fl_entry; struct list_head rl_entry; bool free; int type; u8 type; u32 offset; u32 length; }; Loading