Message ID | 1422000306-27926-1-git-send-email-thierry.reding@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On 23 January 2015 at 18:05, Thierry Reding <thierry.reding@gmail.com> wrote: > From: Thierry Reding <treding@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. This seems fine to me, Chris, Daniel or Thomas, any objections? Dave.
On Fri, Jan 23, 2015 at 3:05 AM, Thierry Reding <thierry.reding@gmail.com> wrote: > From: Thierry Reding <treding@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@nvidia.com> Looks reasonable to me: Reviewed-by: Alex Deucher <alexander.deucher@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@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/dri-devel
On 01/26/2015 11:51 PM, Dave Airlie wrote: > On 23 January 2015 at 18:05, Thierry Reding <thierry.reding@gmail.com> wrote: >> From: Thierry Reding <treding@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. > This seems fine to me, Chris, Daniel or Thomas, any objections? > > Dave. This is perfectly fine with me, although I'm a bit curious why the allocation granularity of the IOVA space needs to be 1 byte? Thanks, Thomas
On Tue, Jan 27, 2015 at 07:07:44AM +0100, Thomas Hellstrom wrote: > On 01/26/2015 11:51 PM, Dave Airlie wrote: > > On 23 January 2015 at 18:05, Thierry Reding <thierry.reding@gmail.com> wrote: > >> From: Thierry Reding <treding@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. > > This seems fine to me, Chris, Daniel or Thomas, any objections? > > > > Dave. > > This is perfectly fine with me, although I'm a bit curious why the > allocation granularity of the IOVA space needs to be 1 byte? Are you referring to the 4 GiB - 1 comment? The point I was trying to make is not that the granularity of the IOVA space needs to be 1 byte but rather that using an unsigned long for a size on a 32-bit machine will give you 4 GiB - 1 addresses. The IOMMU page size is still 4 KiB for Tegra. Thierry
On 01/27/2015 09:15 AM, Thierry Reding wrote: > On Tue, Jan 27, 2015 at 07:07:44AM +0100, Thomas Hellstrom wrote: >> On 01/26/2015 11:51 PM, Dave Airlie wrote: >>> On 23 January 2015 at 18:05, Thierry Reding <thierry.reding@gmail.com> wrote: >>>> From: Thierry Reding <treding@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. >>> This seems fine to me, Chris, Daniel or Thomas, any objections? >>> >>> Dave. >> >> This is perfectly fine with me, although I'm a bit curious why the >> allocation granularity of the IOVA space needs to be 1 byte? > > Are you referring to the 4 GiB - 1 comment? The point I was trying to > make is not that the granularity of the IOVA space needs to be 1 byte > but rather that using an unsigned long for a size on a 32-bit machine > will give you 4 GiB - 1 addresses. The IOMMU page size is still 4 KiB > for Tegra. I was rather referring to that if the range manager (drm_mm) is set up to manage pages instead of bytes (like, for example, the TTM VM address space), you'd get 4G - 1 pages, which, I believe, is sufficient on most 32 bit systems? Thanks, /Thomas > > Thierry
On Tue, Jan 27, 2015 at 08:51:12AM +1000, Dave Airlie wrote: > On 23 January 2015 at 18:05, Thierry Reding <thierry.reding@gmail.com> wrote: > > From: Thierry Reding <treding@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. > > This seems fine to me, Chris, Daniel or Thomas, any objections? None, lgtm. Would be worth just tidying the struct up for natural alignment (especially the drm_mm_node) to remove some holes. Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> -Chris
On Tue, Jan 27, 2015 at 09:31:26AM +0100, Thomas Hellstrom wrote: > On 01/27/2015 09:15 AM, Thierry Reding wrote: > > Are you referring to the 4 GiB - 1 comment? The point I was trying to > > make is not that the granularity of the IOVA space needs to be 1 byte > > but rather that using an unsigned long for a size on a 32-bit machine > > will give you 4 GiB - 1 addresses. The IOMMU page size is still 4 KiB > > for Tegra. > > I was rather referring to that if the range manager (drm_mm) is set up > to manage pages instead of bytes > (like, for example, the TTM VM address space), you'd get 4G - 1 pages, > which, I believe, is sufficient on most 32 bit systems? It'd probably also be more efficient on 32-bit systems rather than shifting them over to using 64-bit quantities. If the allocation granularity were to move to pages, would it be worth moving to a pfn-based addressing system too, rather than sticking with a byte address there too?
On Fri, Jan 23, 2015 at 3:05 AM, Thierry Reding <thierry.reding@gmail.com> wrote: > From: Thierry Reding <treding@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@nvidia.com> Did this land yet? I think we need this for for the full fix for the case when device address space does not match CPU address space. E.g., radeons have 40 or 48 bit internal address spaces. On radeon's with 4GB or more vram, the gart aperture ends up above that in the GPU's address space which ends up getting truncated on 32 bit. See the discussion here: http://lists.freedesktop.org/archives/dri-devel/2015-March/078614.html Alex > --- > 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@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/dri-devel
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);