[Intel-gfx] [PATCH] drm/mm: Support 4 GiB and larger ranges
Alex Deucher
alexdeucher at gmail.com
Mon Jan 26 15:09:38 PST 2015
On Fri, Jan 23, 2015 at 3:05 AM, Thierry Reding
<thierry.reding at gmail.com> wrote:
> From: Thierry Reding <treding at nvidia.com>
>
> The current implementation is limited by the number of addresses that
> fit into an unsigned long. This causes problems on 32-bit Tegra where
> unsigned long is 32-bit but drm_mm is used to manage an IOVA space of
> 4 GiB. Given the 32-bit limitation, the range is limited to 4 GiB - 1
> (or 4 GiB - 4 KiB for page granularity).
>
> This commit changes the start and size of the range to be an unsigned
> 64-bit integer, thus allowing much larger ranges to be supported.
>
> Signed-off-by: Thierry Reding <treding at nvidia.com>
Looks reasonable to me:
Reviewed-by: Alex Deucher <alexander.deucher at amd.com>
> ---
> drivers/gpu/drm/drm_mm.c | 152 ++++++++++++++++++++++++-----------------------
> include/drm/drm_mm.h | 52 ++++++++--------
> 2 files changed, 105 insertions(+), 99 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c
> index 04a209e2b66d..7fc6f8bd4821 100644
> --- a/drivers/gpu/drm/drm_mm.c
> +++ b/drivers/gpu/drm/drm_mm.c
> @@ -91,29 +91,29 @@
> */
>
> static struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm,
> - unsigned long size,
> + u64 size,
> unsigned alignment,
> unsigned long color,
> enum drm_mm_search_flags flags);
> static struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_mm *mm,
> - unsigned long size,
> + u64 size,
> unsigned alignment,
> unsigned long color,
> - unsigned long start,
> - unsigned long end,
> + u64 start,
> + u64 end,
> enum drm_mm_search_flags flags);
>
> static void drm_mm_insert_helper(struct drm_mm_node *hole_node,
> struct drm_mm_node *node,
> - unsigned long size, unsigned alignment,
> + u64 size, unsigned alignment,
> unsigned long color,
> enum drm_mm_allocator_flags flags)
> {
> struct drm_mm *mm = hole_node->mm;
> - unsigned long hole_start = drm_mm_hole_node_start(hole_node);
> - unsigned long hole_end = drm_mm_hole_node_end(hole_node);
> - unsigned long adj_start = hole_start;
> - unsigned long adj_end = hole_end;
> + u64 hole_start = drm_mm_hole_node_start(hole_node);
> + u64 hole_end = drm_mm_hole_node_end(hole_node);
> + u64 adj_start = hole_start;
> + u64 adj_end = hole_end;
>
> BUG_ON(node->allocated);
>
> @@ -124,12 +124,15 @@ static void drm_mm_insert_helper(struct drm_mm_node *hole_node,
> adj_start = adj_end - size;
>
> if (alignment) {
> - unsigned tmp = adj_start % alignment;
> - if (tmp) {
> + u64 tmp = adj_start;
> + unsigned rem;
> +
> + rem = do_div(tmp, alignment);
> + if (rem) {
> if (flags & DRM_MM_CREATE_TOP)
> - adj_start -= tmp;
> + adj_start -= rem;
> else
> - adj_start += alignment - tmp;
> + adj_start += alignment - rem;
> }
> }
>
> @@ -176,9 +179,9 @@ static void drm_mm_insert_helper(struct drm_mm_node *hole_node,
> int drm_mm_reserve_node(struct drm_mm *mm, struct drm_mm_node *node)
> {
> struct drm_mm_node *hole;
> - unsigned long end = node->start + node->size;
> - unsigned long hole_start;
> - unsigned long hole_end;
> + u64 end = node->start + node->size;
> + u64 hole_start;
> + u64 hole_end;
>
> BUG_ON(node == NULL);
>
> @@ -227,7 +230,7 @@ EXPORT_SYMBOL(drm_mm_reserve_node);
> * 0 on success, -ENOSPC if there's no suitable hole.
> */
> int drm_mm_insert_node_generic(struct drm_mm *mm, struct drm_mm_node *node,
> - unsigned long size, unsigned alignment,
> + u64 size, unsigned alignment,
> unsigned long color,
> enum drm_mm_search_flags sflags,
> enum drm_mm_allocator_flags aflags)
> @@ -246,16 +249,16 @@ EXPORT_SYMBOL(drm_mm_insert_node_generic);
>
> static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node,
> struct drm_mm_node *node,
> - unsigned long size, unsigned alignment,
> + u64 size, unsigned alignment,
> unsigned long color,
> - unsigned long start, unsigned long end,
> + u64 start, u64 end,
> enum drm_mm_allocator_flags flags)
> {
> struct drm_mm *mm = hole_node->mm;
> - unsigned long hole_start = drm_mm_hole_node_start(hole_node);
> - unsigned long hole_end = drm_mm_hole_node_end(hole_node);
> - unsigned long adj_start = hole_start;
> - unsigned long adj_end = hole_end;
> + u64 hole_start = drm_mm_hole_node_start(hole_node);
> + u64 hole_end = drm_mm_hole_node_end(hole_node);
> + u64 adj_start = hole_start;
> + u64 adj_end = hole_end;
>
> BUG_ON(!hole_node->hole_follows || node->allocated);
>
> @@ -271,12 +274,15 @@ static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node,
> mm->color_adjust(hole_node, color, &adj_start, &adj_end);
>
> if (alignment) {
> - unsigned tmp = adj_start % alignment;
> - if (tmp) {
> + u64 tmp = adj_start;
> + unsigned rem;
> +
> + rem = do_div(tmp, alignment);
> + if (rem) {
> if (flags & DRM_MM_CREATE_TOP)
> - adj_start -= tmp;
> + adj_start -= rem;
> else
> - adj_start += alignment - tmp;
> + adj_start += alignment - rem;
> }
> }
>
> @@ -324,9 +330,9 @@ static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node,
> * 0 on success, -ENOSPC if there's no suitable hole.
> */
> int drm_mm_insert_node_in_range_generic(struct drm_mm *mm, struct drm_mm_node *node,
> - unsigned long size, unsigned alignment,
> + u64 size, unsigned alignment,
> unsigned long color,
> - unsigned long start, unsigned long end,
> + u64 start, u64 end,
> enum drm_mm_search_flags sflags,
> enum drm_mm_allocator_flags aflags)
> {
> @@ -387,32 +393,34 @@ void drm_mm_remove_node(struct drm_mm_node *node)
> }
> EXPORT_SYMBOL(drm_mm_remove_node);
>
> -static int check_free_hole(unsigned long start, unsigned long end,
> - unsigned long size, unsigned alignment)
> +static int check_free_hole(u64 start, u64 end, u64 size, unsigned alignment)
> {
> if (end - start < size)
> return 0;
>
> if (alignment) {
> - unsigned tmp = start % alignment;
> + u64 tmp = start;
> + unsigned rem;
> +
> + rem = do_div(tmp, alignment);
> if (tmp)
> - start += alignment - tmp;
> + start += alignment - rem;
> }
>
> return end >= start + size;
> }
>
> static struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm,
> - unsigned long size,
> + u64 size,
> unsigned alignment,
> unsigned long color,
> enum drm_mm_search_flags flags)
> {
> struct drm_mm_node *entry;
> struct drm_mm_node *best;
> - unsigned long adj_start;
> - unsigned long adj_end;
> - unsigned long best_size;
> + u64 adj_start;
> + u64 adj_end;
> + u64 best_size;
>
> BUG_ON(mm->scanned_blocks);
>
> @@ -421,7 +429,7 @@ static struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm,
>
> __drm_mm_for_each_hole(entry, mm, adj_start, adj_end,
> flags & DRM_MM_SEARCH_BELOW) {
> - unsigned long hole_size = adj_end - adj_start;
> + u64 hole_size = adj_end - adj_start;
>
> if (mm->color_adjust) {
> mm->color_adjust(entry, color, &adj_start, &adj_end);
> @@ -445,18 +453,18 @@ static struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm,
> }
>
> static struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_mm *mm,
> - unsigned long size,
> + u64 size,
> unsigned alignment,
> unsigned long color,
> - unsigned long start,
> - unsigned long end,
> + u64 start,
> + u64 end,
> enum drm_mm_search_flags flags)
> {
> struct drm_mm_node *entry;
> struct drm_mm_node *best;
> - unsigned long adj_start;
> - unsigned long adj_end;
> - unsigned long best_size;
> + u64 adj_start;
> + u64 adj_end;
> + u64 best_size;
>
> BUG_ON(mm->scanned_blocks);
>
> @@ -465,7 +473,7 @@ static struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_
>
> __drm_mm_for_each_hole(entry, mm, adj_start, adj_end,
> flags & DRM_MM_SEARCH_BELOW) {
> - unsigned long hole_size = adj_end - adj_start;
> + u64 hole_size = adj_end - adj_start;
>
> if (adj_start < start)
> adj_start = start;
> @@ -561,7 +569,7 @@ EXPORT_SYMBOL(drm_mm_replace_node);
> * adding/removing nodes to/from the scan list are allowed.
> */
> void drm_mm_init_scan(struct drm_mm *mm,
> - unsigned long size,
> + u64 size,
> unsigned alignment,
> unsigned long color)
> {
> @@ -594,11 +602,11 @@ EXPORT_SYMBOL(drm_mm_init_scan);
> * adding/removing nodes to/from the scan list are allowed.
> */
> void drm_mm_init_scan_with_range(struct drm_mm *mm,
> - unsigned long size,
> + u64 size,
> unsigned alignment,
> unsigned long color,
> - unsigned long start,
> - unsigned long end)
> + u64 start,
> + u64 end)
> {
> mm->scan_color = color;
> mm->scan_alignment = alignment;
> @@ -627,8 +635,8 @@ bool drm_mm_scan_add_block(struct drm_mm_node *node)
> {
> struct drm_mm *mm = node->mm;
> struct drm_mm_node *prev_node;
> - unsigned long hole_start, hole_end;
> - unsigned long adj_start, adj_end;
> + u64 hole_start, hole_end;
> + u64 adj_start, adj_end;
>
> mm->scanned_blocks++;
>
> @@ -731,7 +739,7 @@ EXPORT_SYMBOL(drm_mm_clean);
> *
> * Note that @mm must be cleared to 0 before calling this function.
> */
> -void drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size)
> +void drm_mm_init(struct drm_mm * mm, u64 start, u64 size)
> {
> INIT_LIST_HEAD(&mm->hole_stack);
> mm->scanned_blocks = 0;
> @@ -766,18 +774,17 @@ void drm_mm_takedown(struct drm_mm * mm)
> }
> EXPORT_SYMBOL(drm_mm_takedown);
>
> -static unsigned long drm_mm_debug_hole(struct drm_mm_node *entry,
> - const char *prefix)
> +static u64 drm_mm_debug_hole(struct drm_mm_node *entry,
> + const char *prefix)
> {
> - unsigned long hole_start, hole_end, hole_size;
> + u64 hole_start, hole_end, hole_size;
>
> if (entry->hole_follows) {
> hole_start = drm_mm_hole_node_start(entry);
> hole_end = drm_mm_hole_node_end(entry);
> hole_size = hole_end - hole_start;
> - printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8lu: free\n",
> - prefix, hole_start, hole_end,
> - hole_size);
> + pr_debug("%s %#llx-%#llx: %llu: free\n", prefix, hole_start,
> + hole_end, hole_size);
> return hole_size;
> }
>
> @@ -792,35 +799,34 @@ static unsigned long drm_mm_debug_hole(struct drm_mm_node *entry,
> void drm_mm_debug_table(struct drm_mm *mm, const char *prefix)
> {
> struct drm_mm_node *entry;
> - unsigned long total_used = 0, total_free = 0, total = 0;
> + u64 total_used = 0, total_free = 0, total = 0;
>
> total_free += drm_mm_debug_hole(&mm->head_node, prefix);
>
> drm_mm_for_each_node(entry, mm) {
> - printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8lu: used\n",
> - prefix, entry->start, entry->start + entry->size,
> - entry->size);
> + pr_debug("%s %#llx-%#llx: %llu: used\n", prefix, entry->start,
> + entry->start + entry->size, entry->size);
> total_used += entry->size;
> total_free += drm_mm_debug_hole(entry, prefix);
> }
> total = total_free + total_used;
>
> - printk(KERN_DEBUG "%s total: %lu, used %lu free %lu\n", prefix, total,
> - total_used, total_free);
> + pr_debug("%s total: %llu, used %llu free %llu\n", prefix, total,
> + total_used, total_free);
> }
> EXPORT_SYMBOL(drm_mm_debug_table);
>
> #if defined(CONFIG_DEBUG_FS)
> -static unsigned long drm_mm_dump_hole(struct seq_file *m, struct drm_mm_node *entry)
> +static u64 drm_mm_dump_hole(struct seq_file *m, struct drm_mm_node *entry)
> {
> - unsigned long hole_start, hole_end, hole_size;
> + u64 hole_start, hole_end, hole_size;
>
> if (entry->hole_follows) {
> hole_start = drm_mm_hole_node_start(entry);
> hole_end = drm_mm_hole_node_end(entry);
> hole_size = hole_end - hole_start;
> - seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: free\n",
> - hole_start, hole_end, hole_size);
> + seq_printf(m, "%#llx-%#llx: %llu: free\n", hole_start,
> + hole_end, hole_size);
> return hole_size;
> }
>
> @@ -835,20 +841,20 @@ static unsigned long drm_mm_dump_hole(struct seq_file *m, struct drm_mm_node *en
> int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm)
> {
> struct drm_mm_node *entry;
> - unsigned long total_used = 0, total_free = 0, total = 0;
> + u64 total_used = 0, total_free = 0, total = 0;
>
> total_free += drm_mm_dump_hole(m, &mm->head_node);
>
> drm_mm_for_each_node(entry, mm) {
> - seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: used\n",
> - entry->start, entry->start + entry->size,
> - entry->size);
> + seq_printf(m, "%#016llx-%#016llx: %llu: used\n", entry->start,
> + entry->start + entry->size, entry->size);
> total_used += entry->size;
> total_free += drm_mm_dump_hole(m, entry);
> }
> total = total_free + total_used;
>
> - seq_printf(m, "total: %lu, used %lu free %lu\n", total, total_used, total_free);
> + seq_printf(m, "total: %llu, used %llu free %llu\n", total,
> + total_used, total_free);
> return 0;
> }
> EXPORT_SYMBOL(drm_mm_dump_table);
> diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h
> index a24addfdfcec..0de6290df4da 100644
> --- a/include/drm/drm_mm.h
> +++ b/include/drm/drm_mm.h
> @@ -68,8 +68,8 @@ struct drm_mm_node {
> unsigned scanned_preceeds_hole : 1;
> unsigned allocated : 1;
> unsigned long color;
> - unsigned long start;
> - unsigned long size;
> + u64 start;
> + u64 size;
> struct drm_mm *mm;
> };
>
> @@ -82,16 +82,16 @@ struct drm_mm {
> unsigned int scan_check_range : 1;
> unsigned scan_alignment;
> unsigned long scan_color;
> - unsigned long scan_size;
> - unsigned long scan_hit_start;
> - unsigned long scan_hit_end;
> + u64 scan_size;
> + u64 scan_hit_start;
> + u64 scan_hit_end;
> unsigned scanned_blocks;
> - unsigned long scan_start;
> - unsigned long scan_end;
> + u64 scan_start;
> + u64 scan_end;
> struct drm_mm_node *prev_scanned_node;
>
> void (*color_adjust)(struct drm_mm_node *node, unsigned long color,
> - unsigned long *start, unsigned long *end);
> + u64 *start, u64 *end);
> };
>
> /**
> @@ -124,7 +124,7 @@ static inline bool drm_mm_initialized(struct drm_mm *mm)
> return mm->hole_stack.next;
> }
>
> -static inline unsigned long __drm_mm_hole_node_start(struct drm_mm_node *hole_node)
> +static inline u64 __drm_mm_hole_node_start(struct drm_mm_node *hole_node)
> {
> return hole_node->start + hole_node->size;
> }
> @@ -140,13 +140,13 @@ static inline unsigned long __drm_mm_hole_node_start(struct drm_mm_node *hole_no
> * Returns:
> * Start of the subsequent hole.
> */
> -static inline unsigned long drm_mm_hole_node_start(struct drm_mm_node *hole_node)
> +static inline u64 drm_mm_hole_node_start(struct drm_mm_node *hole_node)
> {
> BUG_ON(!hole_node->hole_follows);
> return __drm_mm_hole_node_start(hole_node);
> }
>
> -static inline unsigned long __drm_mm_hole_node_end(struct drm_mm_node *hole_node)
> +static inline u64 __drm_mm_hole_node_end(struct drm_mm_node *hole_node)
> {
> return list_entry(hole_node->node_list.next,
> struct drm_mm_node, node_list)->start;
> @@ -163,7 +163,7 @@ static inline unsigned long __drm_mm_hole_node_end(struct drm_mm_node *hole_node
> * Returns:
> * End of the subsequent hole.
> */
> -static inline unsigned long drm_mm_hole_node_end(struct drm_mm_node *hole_node)
> +static inline u64 drm_mm_hole_node_end(struct drm_mm_node *hole_node)
> {
> return __drm_mm_hole_node_end(hole_node);
> }
> @@ -222,7 +222,7 @@ int drm_mm_reserve_node(struct drm_mm *mm, struct drm_mm_node *node);
>
> int drm_mm_insert_node_generic(struct drm_mm *mm,
> struct drm_mm_node *node,
> - unsigned long size,
> + u64 size,
> unsigned alignment,
> unsigned long color,
> enum drm_mm_search_flags sflags,
> @@ -245,7 +245,7 @@ int drm_mm_insert_node_generic(struct drm_mm *mm,
> */
> static inline int drm_mm_insert_node(struct drm_mm *mm,
> struct drm_mm_node *node,
> - unsigned long size,
> + u64 size,
> unsigned alignment,
> enum drm_mm_search_flags flags)
> {
> @@ -255,11 +255,11 @@ static inline int drm_mm_insert_node(struct drm_mm *mm,
>
> int drm_mm_insert_node_in_range_generic(struct drm_mm *mm,
> struct drm_mm_node *node,
> - unsigned long size,
> + u64 size,
> unsigned alignment,
> unsigned long color,
> - unsigned long start,
> - unsigned long end,
> + u64 start,
> + u64 end,
> enum drm_mm_search_flags sflags,
> enum drm_mm_allocator_flags aflags);
> /**
> @@ -282,10 +282,10 @@ int drm_mm_insert_node_in_range_generic(struct drm_mm *mm,
> */
> static inline int drm_mm_insert_node_in_range(struct drm_mm *mm,
> struct drm_mm_node *node,
> - unsigned long size,
> + u64 size,
> unsigned alignment,
> - unsigned long start,
> - unsigned long end,
> + u64 start,
> + u64 end,
> enum drm_mm_search_flags flags)
> {
> return drm_mm_insert_node_in_range_generic(mm, node, size, alignment,
> @@ -296,21 +296,21 @@ static inline int drm_mm_insert_node_in_range(struct drm_mm *mm,
> void drm_mm_remove_node(struct drm_mm_node *node);
> void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new);
> void drm_mm_init(struct drm_mm *mm,
> - unsigned long start,
> - unsigned long size);
> + u64 start,
> + u64 size);
> void drm_mm_takedown(struct drm_mm *mm);
> bool drm_mm_clean(struct drm_mm *mm);
>
> void drm_mm_init_scan(struct drm_mm *mm,
> - unsigned long size,
> + u64 size,
> unsigned alignment,
> unsigned long color);
> void drm_mm_init_scan_with_range(struct drm_mm *mm,
> - unsigned long size,
> + u64 size,
> unsigned alignment,
> unsigned long color,
> - unsigned long start,
> - unsigned long end);
> + u64 start,
> + u64 end);
> bool drm_mm_scan_add_block(struct drm_mm_node *node);
> bool drm_mm_scan_remove_block(struct drm_mm_node *node);
>
> --
> 2.1.3
>
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
More information about the Intel-gfx
mailing list