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

Chris Wilson chris at chris-wilson.co.uk
Tue Oct 8 12:09:57 UTC 2019


Quoting Matthew Auld (2019-10-08 12:57:50)
> On 08/10/2019 09:59, Chris Wilson wrote:
> > 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.
> 
> No good reason, I guess it just stems from using "struct resource 
> region". Maybe for the object_create interface we should just use u64?

resource_size_t is definitely a better starting point than size_t, and
afaik is the preferred type for this physical usage, even when
dma_addr_t conflicts. But that just feels strange, and I couldn't find
any definitive guide. So writing down why we chose the type will help
the inevitable later discussions.
 
> On that topic should we also stop using "struct resource" here, since 
> that's starting to get confusing, maybe use u64 there also?

Well, I'm still looking at struct resource and thinking/hoping it may
lead to us reusing more shared lib/ routines. So I'm ambivalent here. :)

My core objective here is supporting [in thought experiments at least]
4+GiB local memory on 32b platforms. To pull it off would need a bit
more cleaning up (so that we never expose more than we have to) to stay
within the dma budget -- and that has interesting ramifications onto
iomem (we would need a mappable/non-mappable split again, or maybe the
HW will only allow what can be mapped???)
-Chris


More information about the Intel-gfx mailing list