On Sat, Jul 16, 2022 at 2:35 PM Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx> wrote: > > That said, even those type simplifications do not fix the fundamental > issue. That "DIV_ROUND_UP()" still ends up being a 64-bit divide, > although now it's at least a "64-by-32" bit divide. Hmm. The "DIV_ROUND_UP()" issue could be solved by just making the rule be that the max_segment size is always a power of two. Then you don't need the (expensive!) DIV_ROUND_UP(), and can just use the regular "round_up()" that works on powers-of-two. And the simplest way to do that is to just make "max_segments" be 2GB. The whole "round_down(UINT_MAX, page_alignment)" seems entirely pointless. Do you really want segments that are some odd number just under the 4GB mark, and force expensive divides? For consistency, I used the same value in i915_rsgt_from_buddy_resource(). I have no idea if that makes sense. Anyway, the attached patch is COMPLETELY UNTESTED. But it at least seems to compile. Maybe. Linus
drivers/gpu/drm/i915/i915_scatterlist.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_scatterlist.c b/drivers/gpu/drm/i915/i915_scatterlist.c index f63b50b71e10..830dcd833d4e 100644 --- a/drivers/gpu/drm/i915/i915_scatterlist.c +++ b/drivers/gpu/drm/i915/i915_scatterlist.c @@ -81,7 +81,9 @@ struct i915_refct_sgt *i915_rsgt_from_mm_node(const struct drm_mm_node *node, u64 region_start, u64 page_alignment) { - const u64 max_segment = round_down(UINT_MAX, page_alignment); + // Make sure max_segment (and thus segment_pages) is + // a power of two that fits in 32 bits. + const u64 max_segment = 1ul << 31; u64 segment_pages = max_segment >> PAGE_SHIFT; u64 block_size, offset, prev_end; struct i915_refct_sgt *rsgt; @@ -96,7 +98,7 @@ struct i915_refct_sgt *i915_rsgt_from_mm_node(const struct drm_mm_node *node, i915_refct_sgt_init(rsgt, node->size << PAGE_SHIFT); st = &rsgt->table; - if (sg_alloc_table(st, DIV_ROUND_UP(node->size, segment_pages), + if (sg_alloc_table(st, round_up(node->size, segment_pages), GFP_KERNEL)) { i915_refct_sgt_put(rsgt); return ERR_PTR(-ENOMEM); @@ -159,7 +161,7 @@ struct i915_refct_sgt *i915_rsgt_from_buddy_resource(struct ttm_resource *res, { struct i915_ttm_buddy_resource *bman_res = to_ttm_buddy_resource(res); const u64 size = res->num_pages << PAGE_SHIFT; - const u64 max_segment = round_down(UINT_MAX, page_alignment); + const u64 max_segment = 1u << 31; struct drm_buddy *mm = bman_res->mm; struct list_head *blocks = &bman_res->blocks; struct drm_buddy_block *block;