[Intel-gfx] [PATCH v3 02/21] drm/i915: introduce intel_memory_region

Chris Wilson chris at chris-wilson.co.uk
Tue Oct 8 08:59:24 UTC 2019


Quoting Matthew Auld (2019-10-04 18:04:33)
> +int
> +i915_gem_object_get_pages_buddy(struct drm_i915_gem_object *obj)
> +{
> +       struct intel_memory_region *mem = obj->mm.region;
> +       struct list_head *blocks = &obj->mm.blocks;
> +       unsigned int flags = I915_ALLOC_MIN_PAGE_SIZE;
> +       resource_size_t size = obj->base.size;
> +       resource_size_t prev_end;
> +       struct i915_buddy_block *block;
> +       struct sg_table *st;
> +       struct scatterlist *sg;
> +       unsigned int sg_page_sizes;
> +       unsigned long i;
> +       int ret;
> +
> +       st = kmalloc(sizeof(*st), GFP_KERNEL);
> +       if (!st)
> +               return -ENOMEM;
> +
> +       if (sg_alloc_table(st, size >> ilog2(mem->mm.chunk_size), GFP_KERNEL)) {
> +               kfree(st);
> +               return -ENOMEM;
> +       }
> +
> +       ret = __intel_memory_region_get_pages_buddy(mem, size, flags, blocks);
> +       if (ret)
> +               goto err_free_sg;
> +
> +       GEM_BUG_ON(list_empty(blocks));
> +
> +       sg = st->sgl;
> +       st->nents = 0;
> +       sg_page_sizes = 0;
> +       i = 0;
> +
> +       list_for_each_entry(block, blocks, link) {
> +               u64 block_size, offset;
> +
> +               block_size = i915_buddy_block_size(&mem->mm, block);
> +               offset = i915_buddy_block_offset(block);
> +
> +               GEM_BUG_ON(overflows_type(block_size, sg->length));
> +
> +               if (!i || offset != prev_end ||
> +                   add_overflows_t(typeof(sg->length), sg->length, block_size)) {
> +                       if (i) {

i is only being here to detect the start.
prev_end = (resource_size_t)-1;
Then I don't have to worry about i overflowing, although that seems
harmless, and as ridiculous as that may be.

> +                               sg_page_sizes |= sg->length;
> +                               sg = __sg_next(sg);
> +                       }
> +
> +                       sg_dma_address(sg) = mem->region.start + offset;
> +                       sg_dma_len(sg) = block_size;
> +
> +                       sg->length = block_size;
> +
> +                       st->nents++;
> +               } else {
> +                       sg->length += block_size;
> +                       sg_dma_len(sg) += block_size;
> +               }
> +
> +               prev_end = offset + block_size;
> +               i++;
> +       };
> +
> +       sg_page_sizes |= sg->length;
> +       sg_mark_end(sg);
> +       i915_sg_trim(st);
> +
> +       __i915_gem_object_set_pages(obj, st, sg_page_sizes);
> +
> +       return 0;
> +
> +err_free_sg:
> +       sg_free_table(st);
> +       kfree(st);
> +       return ret;
> +}

> +struct drm_i915_gem_object *
> +i915_gem_object_create_region(struct intel_memory_region *mem,
> +                             resource_size_t size,
> +                             unsigned int flags)
> +{
> +       struct drm_i915_gem_object *obj;
> +
> +       if (!mem)
> +               return ERR_PTR(-ENODEV);
> +
> +       size = round_up(size, mem->min_page_size);
> +
> +       GEM_BUG_ON(!size);
> +       GEM_BUG_ON(!IS_ALIGNED(size, I915_GTT_MIN_ALIGNMENT));
> +

Put the FIXME here from the start

> +       if (size >> PAGE_SHIFT > INT_MAX)
> +               return ERR_PTR(-E2BIG);
> +
> +       if (overflows_type(size, obj->base.size))
> +               return ERR_PTR(-E2BIG);
> +
> +       return mem->ops->create_object(mem, size, flags);
> +}

I'm happy with this. But I would like a discussion on why
resource_size_t was chosen and for that rationale to be captured in the
code comments. At the end of the day, we need to bump obj->base.size to
suit.
-Chris


More information about the Intel-gfx mailing list