Am 03.12.19 um 14:22 schrieb Thomas Hellström (VMware):
From: Thomas Hellstrom <thellst...@vmware.com>

Using huge page-table entries require that the start of a buffer object
is huge page size aligned. So introduce a ttm_bo_man_get_node_huge()
function that attempts to accomplish this for allocations that are larger
than the huge page size, and provide a new range-manager instance that
uses that function.

I still don't think that this is a good idea.

The driver/userspace should just use a proper alignment if it wants to use huge pages.

Regards,
Christian.


Cc: Andrew Morton <a...@linux-foundation.org>
Cc: Michal Hocko <mho...@suse.com>
Cc: "Matthew Wilcox (Oracle)" <wi...@infradead.org>
Cc: "Kirill A. Shutemov" <kirill.shute...@linux.intel.com>
Cc: Ralph Campbell <rcampb...@nvidia.com>
Cc: "Jérôme Glisse" <jgli...@redhat.com>
Cc: "Christian König" <christian.koe...@amd.com>
Signed-off-by: Thomas Hellstrom <thellst...@vmware.com>
---
  drivers/gpu/drm/ttm/ttm_bo_manager.c | 92 ++++++++++++++++++++++++++++
  include/drm/ttm/ttm_bo_driver.h      |  1 +
  2 files changed, 93 insertions(+)

diff --git a/drivers/gpu/drm/ttm/ttm_bo_manager.c 
b/drivers/gpu/drm/ttm/ttm_bo_manager.c
index 18d3debcc949..26aa1a2ae7f1 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_manager.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_manager.c
@@ -89,6 +89,89 @@ static int ttm_bo_man_get_node(struct ttm_mem_type_manager 
*man,
        return 0;
  }
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+static int ttm_bo_insert_aligned(struct drm_mm *mm, struct drm_mm_node *node,
+                                unsigned long align_pages,
+                                const struct ttm_place *place,
+                                struct ttm_mem_reg *mem,
+                                unsigned long lpfn,
+                                enum drm_mm_insert_mode mode)
+{
+       if (align_pages >= mem->page_alignment &&
+           (!mem->page_alignment || align_pages % mem->page_alignment == 0)) {
+               return drm_mm_insert_node_in_range(mm, node,
+                                                  mem->num_pages,
+                                                  align_pages, 0,
+                                                  place->fpfn, lpfn, mode);
+       }
+
+       return -ENOSPC;
+}
+
+static int ttm_bo_man_get_node_huge(struct ttm_mem_type_manager *man,
+                                   struct ttm_buffer_object *bo,
+                                   const struct ttm_place *place,
+                                   struct ttm_mem_reg *mem)
+{
+       struct ttm_range_manager *rman = (struct ttm_range_manager *) man->priv;
+       struct drm_mm *mm = &rman->mm;
+       struct drm_mm_node *node;
+       unsigned long align_pages;
+       unsigned long lpfn;
+       enum drm_mm_insert_mode mode = DRM_MM_INSERT_BEST;
+       int ret;
+
+       node = kzalloc(sizeof(*node), GFP_KERNEL);
+       if (!node)
+               return -ENOMEM;
+
+       lpfn = place->lpfn;
+       if (!lpfn)
+               lpfn = man->size;
+
+       mode = DRM_MM_INSERT_BEST;
+       if (place->flags & TTM_PL_FLAG_TOPDOWN)
+               mode = DRM_MM_INSERT_HIGH;
+
+       spin_lock(&rman->lock);
+       if (IS_ENABLED(CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD)) {
+               align_pages = (HPAGE_PUD_SIZE >> PAGE_SHIFT);
+               if (mem->num_pages >= align_pages) {
+                       ret = ttm_bo_insert_aligned(mm, node, align_pages,
+                                                   place, mem, lpfn, mode);
+                       if (!ret)
+                               goto found_unlock;
+               }
+       }
+
+       align_pages = (HPAGE_PMD_SIZE >> PAGE_SHIFT);
+       if (mem->num_pages >= align_pages) {
+               ret = ttm_bo_insert_aligned(mm, node, align_pages, place, mem,
+                                           lpfn, mode);
+               if (!ret)
+                       goto found_unlock;
+       }
+
+       ret = drm_mm_insert_node_in_range(mm, node, mem->num_pages,
+                                         mem->page_alignment, 0,
+                                         place->fpfn, lpfn, mode);
+found_unlock:
+       spin_unlock(&rman->lock);
+
+       if (unlikely(ret)) {
+               kfree(node);
+       } else {
+               mem->mm_node = node;
+               mem->start = node->start;
+       }
+
+       return 0;
+}
+#else
+#define ttm_bo_man_get_node_huge ttm_bo_man_get_node
+#endif
+
+
  static void ttm_bo_man_put_node(struct ttm_mem_type_manager *man,
                                struct ttm_mem_reg *mem)
  {
@@ -154,3 +237,12 @@ const struct ttm_mem_type_manager_func ttm_bo_manager_func 
= {
        .debug = ttm_bo_man_debug
  };
  EXPORT_SYMBOL(ttm_bo_manager_func);
+
+const struct ttm_mem_type_manager_func ttm_bo_manager_huge_func = {
+       .init = ttm_bo_man_init,
+       .takedown = ttm_bo_man_takedown,
+       .get_node = ttm_bo_man_get_node_huge,
+       .put_node = ttm_bo_man_put_node,
+       .debug = ttm_bo_man_debug
+};
+EXPORT_SYMBOL(ttm_bo_manager_huge_func);
diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h
index cac7a8a0825a..868bd0d4be6a 100644
--- a/include/drm/ttm/ttm_bo_driver.h
+++ b/include/drm/ttm/ttm_bo_driver.h
@@ -888,5 +888,6 @@ int ttm_bo_pipeline_gutting(struct ttm_buffer_object *bo);
  pgprot_t ttm_io_prot(uint32_t caching_flags, pgprot_t tmp);
extern const struct ttm_mem_type_manager_func ttm_bo_manager_func;
+extern const struct ttm_mem_type_manager_func ttm_bo_manager_huge_func;
#endif

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to