On Tue, Oct 5, 2021 at 10:11 AM Thomas Zimmermann <tzimmermann@xxxxxxx> wrote: > > Allocation and pinning helpers for struct gtt_range are GEM functions, > so move them to gem.c. No functional changes. > > v2: > * keep docs for psb_gtt_{attach,detach}_pages() (Patrik) > Bonus point for getting rid of psb_gtt_kref_put(); Acked-by: Patrik Jakobsson <patrik.r.jakobsson@xxxxxxxxx> > Signed-off-by: Thomas Zimmermann <tzimmermann@xxxxxxx> > --- > drivers/gpu/drm/gma500/framebuffer.c | 1 - > drivers/gpu/drm/gma500/gem.c | 144 ++++++++++++++-- > drivers/gpu/drm/gma500/gem.h | 8 + > drivers/gpu/drm/gma500/gma_display.c | 1 + > drivers/gpu/drm/gma500/gtt.c | 190 +-------------------- > drivers/gpu/drm/gma500/gtt.h | 11 +- > drivers/gpu/drm/gma500/psb_intel_display.c | 1 + > 7 files changed, 147 insertions(+), 209 deletions(-) > > diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c > index 321e416489a9..ce92d11bd20f 100644 > --- a/drivers/gpu/drm/gma500/framebuffer.c > +++ b/drivers/gpu/drm/gma500/framebuffer.c > @@ -25,7 +25,6 @@ > > #include "framebuffer.h" > #include "gem.h" > -#include "gtt.h" > #include "psb_drv.h" > #include "psb_intel_drv.h" > #include "psb_intel_reg.h" > diff --git a/drivers/gpu/drm/gma500/gem.c b/drivers/gpu/drm/gma500/gem.c > index 5ae54c9d2819..a41990dbcc0e 100644 > --- a/drivers/gpu/drm/gma500/gem.c > +++ b/drivers/gpu/drm/gma500/gem.c > @@ -19,6 +19,100 @@ > #include "gem.h" > #include "psb_drv.h" > > +/* > + * Pin and build an in-kernel list of the pages that back our GEM object. > + * While we hold this the pages cannot be swapped out. This is protected > + * via the gtt mutex which the caller must hold. > + */ > +static int psb_gtt_attach_pages(struct gtt_range *gt) > +{ > + struct page **pages; > + > + WARN_ON(gt->pages); > + > + pages = drm_gem_get_pages(>->gem); > + if (IS_ERR(pages)) > + return PTR_ERR(pages); > + > + gt->npage = gt->gem.size / PAGE_SIZE; > + gt->pages = pages; > + > + return 0; > +} > + > +/* > + * Undo the effect of psb_gtt_attach_pages. At this point the pages > + * must have been removed from the GTT as they could now be paged out > + * and move bus address. This is protected via the gtt mutex which the > + * caller must hold. > + */ > +static void psb_gtt_detach_pages(struct gtt_range *gt) > +{ > + drm_gem_put_pages(>->gem, gt->pages, true, false); > + gt->pages = NULL; > +} > + > +int psb_gtt_pin(struct gtt_range *gt) > +{ > + int ret = 0; > + struct drm_device *dev = gt->gem.dev; > + struct drm_psb_private *dev_priv = to_drm_psb_private(dev); > + u32 gpu_base = dev_priv->gtt.gatt_start; > + > + mutex_lock(&dev_priv->gtt_mutex); > + > + if (gt->in_gart == 0 && gt->stolen == 0) { > + ret = psb_gtt_attach_pages(gt); > + if (ret < 0) > + goto out; > + ret = psb_gtt_insert(dev, gt, 0); > + if (ret < 0) { > + psb_gtt_detach_pages(gt); > + goto out; > + } > + psb_mmu_insert_pages(psb_mmu_get_default_pd(dev_priv->mmu), > + gt->pages, (gpu_base + gt->offset), > + gt->npage, 0, 0, PSB_MMU_CACHED_MEMORY); > + } > + gt->in_gart++; > +out: > + mutex_unlock(&dev_priv->gtt_mutex); > + return ret; > +} > + > +void psb_gtt_unpin(struct gtt_range *gt) > +{ > + struct drm_device *dev = gt->gem.dev; > + struct drm_psb_private *dev_priv = to_drm_psb_private(dev); > + u32 gpu_base = dev_priv->gtt.gatt_start; > + > + mutex_lock(&dev_priv->gtt_mutex); > + > + WARN_ON(!gt->in_gart); > + > + gt->in_gart--; > + if (gt->in_gart == 0 && gt->stolen == 0) { > + psb_mmu_remove_pages(psb_mmu_get_default_pd(dev_priv->mmu), > + (gpu_base + gt->offset), gt->npage, 0, 0); > + psb_gtt_remove(dev, gt); > + psb_gtt_detach_pages(gt); > + } > + > + mutex_unlock(&dev_priv->gtt_mutex); > +} > + > +void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt) > +{ > + /* Undo the mmap pin if we are destroying the object */ > + if (gt->mmapping) { > + psb_gtt_unpin(gt); > + gt->mmapping = 0; > + } > + WARN_ON(gt->in_gart && !gt->stolen); > + release_resource(>->resource); > + kfree(gt); > +} > + > static vm_fault_t psb_gem_fault(struct vm_fault *vmf); > > static void psb_gem_free_object(struct drm_gem_object *obj) > @@ -44,19 +138,43 @@ const struct drm_gem_object_funcs psb_gem_object_funcs = { > .vm_ops = &psb_gem_vm_ops, > }; > > -/** > - * psb_gem_create - create a mappable object > - * @file: the DRM file of the client > - * @dev: our device > - * @size: the size requested > - * @handlep: returned handle (opaque number) > - * @stolen: unused > - * @align: unused > - * > - * Create a GEM object, fill in the boilerplate and attach a handle to > - * it so that userspace can speak about it. This does the core work > - * for the various methods that do/will create GEM objects for things > - */ > +struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len, > + const char *name, int backed, u32 align) > +{ > + struct drm_psb_private *dev_priv = to_drm_psb_private(dev); > + struct gtt_range *gt; > + struct resource *r = dev_priv->gtt_mem; > + int ret; > + unsigned long start, end; > + > + if (backed) { > + /* The start of the GTT is the stolen pages */ > + start = r->start; > + end = r->start + dev_priv->gtt.stolen_size - 1; > + } else { > + /* The rest we will use for GEM backed objects */ > + start = r->start + dev_priv->gtt.stolen_size; > + end = r->end; > + } > + > + gt = kzalloc(sizeof(struct gtt_range), GFP_KERNEL); > + if (gt == NULL) > + return NULL; > + gt->resource.name = name; > + gt->stolen = backed; > + gt->in_gart = backed; > + /* Ensure this is set for non GEM objects */ > + gt->gem.dev = dev; > + ret = allocate_resource(dev_priv->gtt_mem, >->resource, > + len, start, end, align, NULL, NULL); > + if (ret == 0) { > + gt->offset = gt->resource.start - r->start; > + return gt; > + } > + kfree(gt); > + return NULL; > +} > + > int psb_gem_create(struct drm_file *file, struct drm_device *dev, u64 size, > u32 *handlep, int stolen, u32 align) > { > diff --git a/drivers/gpu/drm/gma500/gem.h b/drivers/gpu/drm/gma500/gem.h > index bae6454ead29..275494aedd4c 100644 > --- a/drivers/gpu/drm/gma500/gem.h > +++ b/drivers/gpu/drm/gma500/gem.h > @@ -8,6 +8,8 @@ > #ifndef _GEM_H > #define _GEM_H > > +#include <drm/drm_gem.h> > + > struct drm_device; > > extern const struct drm_gem_object_funcs psb_gem_object_funcs; > @@ -15,4 +17,10 @@ extern const struct drm_gem_object_funcs psb_gem_object_funcs; > extern int psb_gem_create(struct drm_file *file, struct drm_device *dev, > u64 size, u32 *handlep, int stolen, u32 align); > > +struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len, const char *name, > + int backed, u32 align); > +void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt); > +int psb_gtt_pin(struct gtt_range *gt); > +void psb_gtt_unpin(struct gtt_range *gt); > + > #endif > diff --git a/drivers/gpu/drm/gma500/gma_display.c b/drivers/gpu/drm/gma500/gma_display.c > index cbcecbaa041b..ecf8153416ac 100644 > --- a/drivers/gpu/drm/gma500/gma_display.c > +++ b/drivers/gpu/drm/gma500/gma_display.c > @@ -15,6 +15,7 @@ > #include <drm/drm_vblank.h> > > #include "framebuffer.h" > +#include "gem.h" > #include "gma_display.h" > #include "psb_drv.h" > #include "psb_intel_drv.h" > diff --git a/drivers/gpu/drm/gma500/gtt.c b/drivers/gpu/drm/gma500/gtt.c > index 55a2a6919533..0aacf7122e32 100644 > --- a/drivers/gpu/drm/gma500/gtt.c > +++ b/drivers/gpu/drm/gma500/gtt.c > @@ -71,8 +71,7 @@ static u32 __iomem *psb_gtt_entry(struct drm_device *dev, struct gtt_range *r) > * the GTT. This is protected via the gtt mutex which the caller > * must hold. > */ > -static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r, > - int resume) > +int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r, int resume) > { > u32 __iomem *gtt_slot; > u32 pte; > @@ -116,7 +115,7 @@ static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r, > * page table entries with the dummy page. This is protected via the gtt > * mutex which the caller must hold. > */ > -static void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r) > +void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r) > { > struct drm_psb_private *dev_priv = to_drm_psb_private(dev); > u32 __iomem *gtt_slot; > @@ -135,191 +134,6 @@ static void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r) > set_pages_array_wb(r->pages, r->npage); > } > > -/** > - * psb_gtt_attach_pages - attach and pin GEM pages > - * @gt: the gtt range > - * > - * Pin and build an in kernel list of the pages that back our GEM object. > - * While we hold this the pages cannot be swapped out. This is protected > - * via the gtt mutex which the caller must hold. > - */ > -static int psb_gtt_attach_pages(struct gtt_range *gt) > -{ > - struct page **pages; > - > - WARN_ON(gt->pages); > - > - pages = drm_gem_get_pages(>->gem); > - if (IS_ERR(pages)) > - return PTR_ERR(pages); > - > - gt->npage = gt->gem.size / PAGE_SIZE; > - gt->pages = pages; > - > - return 0; > -} > - > -/** > - * psb_gtt_detach_pages - attach and pin GEM pages > - * @gt: the gtt range > - * > - * Undo the effect of psb_gtt_attach_pages. At this point the pages > - * must have been removed from the GTT as they could now be paged out > - * and move bus address. This is protected via the gtt mutex which the > - * caller must hold. > - */ > -static void psb_gtt_detach_pages(struct gtt_range *gt) > -{ > - drm_gem_put_pages(>->gem, gt->pages, true, false); > - gt->pages = NULL; > -} > - > -/** > - * psb_gtt_pin - pin pages into the GTT > - * @gt: range to pin > - * > - * Pin a set of pages into the GTT. The pins are refcounted so that > - * multiple pins need multiple unpins to undo. > - * > - * Non GEM backed objects treat this as a no-op as they are always GTT > - * backed objects. > - */ > -int psb_gtt_pin(struct gtt_range *gt) > -{ > - int ret = 0; > - struct drm_device *dev = gt->gem.dev; > - struct drm_psb_private *dev_priv = to_drm_psb_private(dev); > - u32 gpu_base = dev_priv->gtt.gatt_start; > - > - mutex_lock(&dev_priv->gtt_mutex); > - > - if (gt->in_gart == 0 && gt->stolen == 0) { > - ret = psb_gtt_attach_pages(gt); > - if (ret < 0) > - goto out; > - ret = psb_gtt_insert(dev, gt, 0); > - if (ret < 0) { > - psb_gtt_detach_pages(gt); > - goto out; > - } > - psb_mmu_insert_pages(psb_mmu_get_default_pd(dev_priv->mmu), > - gt->pages, (gpu_base + gt->offset), > - gt->npage, 0, 0, PSB_MMU_CACHED_MEMORY); > - } > - gt->in_gart++; > -out: > - mutex_unlock(&dev_priv->gtt_mutex); > - return ret; > -} > - > -/** > - * psb_gtt_unpin - Drop a GTT pin requirement > - * @gt: range to pin > - * > - * Undoes the effect of psb_gtt_pin. On the last drop the GEM object > - * will be removed from the GTT which will also drop the page references > - * and allow the VM to clean up or page stuff. > - * > - * Non GEM backed objects treat this as a no-op as they are always GTT > - * backed objects. > - */ > -void psb_gtt_unpin(struct gtt_range *gt) > -{ > - struct drm_device *dev = gt->gem.dev; > - struct drm_psb_private *dev_priv = to_drm_psb_private(dev); > - u32 gpu_base = dev_priv->gtt.gatt_start; > - > - mutex_lock(&dev_priv->gtt_mutex); > - > - WARN_ON(!gt->in_gart); > - > - gt->in_gart--; > - if (gt->in_gart == 0 && gt->stolen == 0) { > - psb_mmu_remove_pages(psb_mmu_get_default_pd(dev_priv->mmu), > - (gpu_base + gt->offset), gt->npage, 0, 0); > - psb_gtt_remove(dev, gt); > - psb_gtt_detach_pages(gt); > - } > - > - mutex_unlock(&dev_priv->gtt_mutex); > -} > - > -/* > - * GTT resource allocator - allocate and manage GTT address space > - */ > - > -/** > - * psb_gtt_alloc_range - allocate GTT address space > - * @dev: Our DRM device > - * @len: length (bytes) of address space required > - * @name: resource name > - * @backed: resource should be backed by stolen pages > - * @align: requested alignment > - * > - * Ask the kernel core to find us a suitable range of addresses > - * to use for a GTT mapping. > - * > - * Returns a gtt_range structure describing the object, or NULL on > - * error. On successful return the resource is both allocated and marked > - * as in use. > - */ > -struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len, > - const char *name, int backed, u32 align) > -{ > - struct drm_psb_private *dev_priv = to_drm_psb_private(dev); > - struct gtt_range *gt; > - struct resource *r = dev_priv->gtt_mem; > - int ret; > - unsigned long start, end; > - > - if (backed) { > - /* The start of the GTT is the stolen pages */ > - start = r->start; > - end = r->start + dev_priv->gtt.stolen_size - 1; > - } else { > - /* The rest we will use for GEM backed objects */ > - start = r->start + dev_priv->gtt.stolen_size; > - end = r->end; > - } > - > - gt = kzalloc(sizeof(struct gtt_range), GFP_KERNEL); > - if (gt == NULL) > - return NULL; > - gt->resource.name = name; > - gt->stolen = backed; > - gt->in_gart = backed; > - /* Ensure this is set for non GEM objects */ > - gt->gem.dev = dev; > - ret = allocate_resource(dev_priv->gtt_mem, >->resource, > - len, start, end, align, NULL, NULL); > - if (ret == 0) { > - gt->offset = gt->resource.start - r->start; > - return gt; > - } > - kfree(gt); > - return NULL; > -} > - > -/** > - * psb_gtt_free_range - release GTT address space > - * @dev: our DRM device > - * @gt: a mapping created with psb_gtt_alloc_range > - * > - * Release a resource that was allocated with psb_gtt_alloc_range. If the > - * object has been pinned by mmap users we clean this up here currently. > - */ > -void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt) > -{ > - /* Undo the mmap pin if we are destroying the object */ > - if (gt->mmapping) { > - psb_gtt_unpin(gt); > - gt->mmapping = 0; > - } > - WARN_ON(gt->in_gart && !gt->stolen); > - release_resource(>->resource); > - kfree(gt); > -} > - > static void psb_gtt_alloc(struct drm_device *dev) > { > struct drm_psb_private *dev_priv = to_drm_psb_private(dev); > diff --git a/drivers/gpu/drm/gma500/gtt.h b/drivers/gpu/drm/gma500/gtt.h > index 2bf165849ebe..36162b545570 100644 > --- a/drivers/gpu/drm/gma500/gtt.h > +++ b/drivers/gpu/drm/gma500/gtt.h > @@ -41,12 +41,9 @@ struct gtt_range { > > #define to_gtt_range(x) container_of(x, struct gtt_range, gem) > > -extern struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len, > - const char *name, int backed, > - u32 align); > -extern void psb_gtt_kref_put(struct gtt_range *gt); > -extern void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt); > -extern int psb_gtt_pin(struct gtt_range *gt); > -extern void psb_gtt_unpin(struct gtt_range *gt); > extern int psb_gtt_restore(struct drm_device *dev); > + > +int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r, int resume); > +void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r); > + > #endif > diff --git a/drivers/gpu/drm/gma500/psb_intel_display.c b/drivers/gpu/drm/gma500/psb_intel_display.c > index f5f259fde88e..18d5f7e5889e 100644 > --- a/drivers/gpu/drm/gma500/psb_intel_display.c > +++ b/drivers/gpu/drm/gma500/psb_intel_display.c > @@ -12,6 +12,7 @@ > #include <drm/drm_plane_helper.h> > > #include "framebuffer.h" > +#include "gem.h" > #include "gma_display.h" > #include "power.h" > #include "psb_drv.h" > -- > 2.33.0 >