[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