From: Ben Widawsky <ben@bwidawsk.net>
To: David Herrmann <dh.herrmann@gmail.com>
Cc: Intel GFX <intel-gfx@lists.freedesktop.org>,
"dri-devel@lists.freedesktop.org"
<dri-devel@lists.freedesktop.org>
Subject: Re: [PATCH 1/6] drm: pre allocate node for create_block
Date: Thu, 4 Jul 2013 13:03:12 -0700 [thread overview]
Message-ID: <20130704200312.GA16758@bwidawsk.net> (raw)
In-Reply-To: <CANq1E4TX0-6bfpnMGg6-YxsbiZt6e2g=rQ8cvKdzVu39Cr4TNA@mail.gmail.com>
On Thu, Jul 04, 2013 at 11:19:58AM +0200, David Herrmann wrote:
> Hi
>
> On Wed, Jul 3, 2013 at 11:45 PM, Ben Widawsky <ben@bwidawsk.net> wrote:
> > For an upcoming patch where we introduce the i915 VMA, it's ideal to
> > have the drm_mm_node as part of the VMA struct (ie. it's pre-allocated).
> > Part of the conversion to VMAs is to kill off obj->gtt_space. Doing this
> > will break a bunch of code, but amongst them are 2 callers of
> > drm_mm_create_block(), both related to stolen memory.
> >
> > It also allows us to embed the drm_mm_node into the object currently
> > which provides a nice transition over to the new code.
> >
> > v2: Reordered to do before ripping out obj->gtt_offset.
> > Some minor cleanups made available because of reordering.
> >
> > CC: <dri-devel@lists.freedesktop.org>
> > Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
> > ---
> > drivers/gpu/drm/drm_mm.c | 16 +++++----------
> > drivers/gpu/drm/i915/i915_gem_gtt.c | 18 +++++++++++++----
> > drivers/gpu/drm/i915/i915_gem_stolen.c | 36 +++++++++++++++++++++++-----------
> > include/drm/drm_mm.h | 9 +++++----
> > 4 files changed, 49 insertions(+), 30 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c
> > index 07cf99c..9e8dfbc 100644
> > --- a/drivers/gpu/drm/drm_mm.c
> > +++ b/drivers/gpu/drm/drm_mm.c
> > @@ -147,12 +147,10 @@ static void drm_mm_insert_helper(struct drm_mm_node *hole_node,
> > }
> > }
> >
> > -struct drm_mm_node *drm_mm_create_block(struct drm_mm *mm,
> > - unsigned long start,
> > - unsigned long size,
> > - bool atomic)
> > +int drm_mm_create_block(struct drm_mm *mm, struct drm_mm_node *node,
> > + unsigned long start, unsigned long size)
> > {
> > - struct drm_mm_node *hole, *node;
> > + struct drm_mm_node *hole;
> > unsigned long end = start + size;
> > unsigned long hole_start;
> > unsigned long hole_end;
> > @@ -161,10 +159,6 @@ struct drm_mm_node *drm_mm_create_block(struct drm_mm *mm,
> > if (hole_start > start || hole_end < end)
> > continue;
> >
> > - node = drm_mm_kmalloc(mm, atomic);
> > - if (unlikely(node == NULL))
> > - return NULL;
> > -
> > node->start = start;
> > node->size = size;
> > node->mm = mm;
> > @@ -184,11 +178,11 @@ struct drm_mm_node *drm_mm_create_block(struct drm_mm *mm,
> > node->hole_follows = 1;
> > }
> >
> > - return node;
> > + return 0;
> > }
> >
> > WARN(1, "no hole found for block 0x%lx + 0x%lx\n", start, size);
> > - return NULL;
> > + return -ENOSPC;
> > }
> > EXPORT_SYMBOL(drm_mm_create_block);
> >
> > diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
> > index 66929ea..5c6fc0e 100644
> > --- a/drivers/gpu/drm/i915/i915_gem_gtt.c
> > +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
> > @@ -629,14 +629,24 @@ void i915_gem_setup_global_gtt(struct drm_device *dev,
> >
> > /* Mark any preallocated objects as occupied */
> > list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
> > + int ret;
> > DRM_DEBUG_KMS("reserving preallocated space: %x + %zx\n",
> > obj->gtt_offset, obj->base.size);
> >
> > BUG_ON(obj->gtt_space != I915_GTT_RESERVED);
> > - obj->gtt_space = drm_mm_create_block(&dev_priv->mm.gtt_space,
> > - obj->gtt_offset,
> > - obj->base.size,
> > - false);
> > + obj->gtt_space = kzalloc(sizeof(*obj->gtt_space), GFP_KERNEL);
> > + if (!obj->gtt_space) {
> > + DRM_ERROR("Failed to preserve all objects\n");
> > + break;
> > + }
> > + ret = drm_mm_create_block(&dev_priv->mm.gtt_space,
> > + obj->gtt_space,
> > + obj->gtt_offset,
> > + obj->base.size);
> > + if (ret) {
> > + DRM_DEBUG_KMS("Reservation failed\n");
> > + kfree(obj->gtt_space);
>
> Are you sure you don't need:
> obj->gtt_space = NULL;
> here?
> I am no expert in i915 gem handling, but looking at i915_gem.c I think
> you might run into bugs if not.
I'm too lazy to actually check, but I believe you're probably right.
It's fixed in a later patch where I added the getters and use
node_allocated so I don't check obj->gtt_space != NULL anymore; but it
would potentially be a painful bisect point.
Thanks for catching it (and the following ones).
>
> Also, why did you add the "break;" above, but not here? I am confused.
The thought at the time was if kzalloc fails at this point, subsequent
kzallocs are really likely to fail also. drm_mm_create_block OTOH is
something I won't pretend to inquire about failure recurrence. I agree
it looks funny though, so I'll change the break to continue.
>
> > + }
> > obj->has_global_gtt_mapping = 1;
> > }
> >
> > diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c
> > index 8e02344..f9db84a 100644
> > --- a/drivers/gpu/drm/i915/i915_gem_stolen.c
> > +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c
> > @@ -330,6 +330,7 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
> > struct drm_i915_private *dev_priv = dev->dev_private;
> > struct drm_i915_gem_object *obj;
> > struct drm_mm_node *stolen;
> > + int ret;
> >
> > if (dev_priv->mm.stolen_base == 0)
> > return NULL;
> > @@ -344,11 +345,15 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
> > if (WARN_ON(size == 0))
> > return NULL;
> >
> > - stolen = drm_mm_create_block(&dev_priv->mm.stolen,
> > - stolen_offset, size,
> > - false);
> > - if (stolen == NULL) {
> > + stolen = kzalloc(sizeof(*stolen), GFP_KERNEL);
> > + if (!stolen)
> > + return NULL;
> > +
> > + ret = drm_mm_create_block(&dev_priv->mm.stolen, stolen, stolen_offset,
> > + size);
> > + if (ret) {
> > DRM_DEBUG_KMS("failed to allocate stolen space\n");
> > + kfree(stolen);
> > return NULL;
> > }
> >
> > @@ -369,13 +374,18 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
> > * later.
> > */
> > if (drm_mm_initialized(&dev_priv->mm.gtt_space)) {
> > - obj->gtt_space = drm_mm_create_block(&dev_priv->mm.gtt_space,
> > - gtt_offset, size,
> > - false);
> > - if (obj->gtt_space == NULL) {
> > + obj->gtt_space = kzalloc(sizeof(*obj->gtt_space), GFP_KERNEL);
> > + if (!obj->gtt_space) {
> > + DRM_DEBUG_KMS("-ENOMEM stolen GTT space\n");
> > + goto unref_out;
> > + }
> > +
> > + ret = drm_mm_create_block(&dev_priv->mm.gtt_space,
> > + obj->gtt_space,
> > + gtt_offset, size);
> > + if (ret) {
> > DRM_DEBUG_KMS("failed to allocate stolen GTT space\n");
> > - drm_gem_object_unreference(&obj->base);
> > - return NULL;
> > + goto unref_out;
>
> Again:
> kfree(obj->gtt_space);
> obj->gtt_space = NULL;
> Otherwise, if gem-cleanup calls drm_mm_put_block() on an already
> removed node, you end up with NULL-derefs in drm_mm.c
>
> > }
> > } else
> > obj->gtt_space = I915_GTT_RESERVED;
> > @@ -385,8 +395,12 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
> >
> > list_add_tail(&obj->global_list, &dev_priv->mm.bound_list);
> > list_add_tail(&obj->mm_list, &dev_priv->mm.inactive_list);
> > -
> > return obj;
> > +
> > +unref_out:
> > + drm_gem_object_unreference(&obj->base);
> > + drm_mm_put_block(stolen);
>
> "stolen" is already cleared by drm_gem_object_unreference(). So that's
> a double-free here.
>
> The drm_mm_create_block() change looks good.
> Cheers
> David
>
Thanks for reviewing the i915 parts so thoroughly :D
>
> > + return NULL;
> > }
> >
> > void
> > diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h
> > index 88591ef..d8b56b7 100644
> > --- a/include/drm/drm_mm.h
> > +++ b/include/drm/drm_mm.h
> > @@ -138,10 +138,10 @@ static inline unsigned long drm_mm_hole_node_end(struct drm_mm_node *hole_node)
> > /*
> > * Basic range manager support (drm_mm.c)
> > */
> > -extern struct drm_mm_node *drm_mm_create_block(struct drm_mm *mm,
> > - unsigned long start,
> > - unsigned long size,
> > - bool atomic);
> > +extern int drm_mm_create_block(struct drm_mm *mm,
> > + struct drm_mm_node *node,
> > + unsigned long start,
> > + unsigned long size);
> > extern struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *node,
> > unsigned long size,
> > unsigned alignment,
> > @@ -155,6 +155,7 @@ extern struct drm_mm_node *drm_mm_get_block_range_generic(
> > unsigned long start,
> > unsigned long end,
> > int atomic);
> > +
> > static inline struct drm_mm_node *drm_mm_get_block(struct drm_mm_node *parent,
> > unsigned long size,
> > unsigned alignment)
> > --
> > 1.8.3.2
> >
> > _______________________________________________
> > dri-devel mailing list
> > dri-devel@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/dri-devel
--
Ben Widawsky, Intel Open Source Technology Center
next prev parent reply other threads:[~2013-07-04 20:03 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-07-03 21:45 [PATCH 1/6] drm: pre allocate node for create_block Ben Widawsky
2013-07-03 21:45 ` [PATCH 2/6] drm/i915: Getter/setter for object attributes Ben Widawsky
2013-07-03 22:55 ` Daniel Vetter
2013-07-04 1:07 ` Ben Widawsky
2013-07-03 21:45 ` [PATCH 3/6] drm/i915: Kill obj->gtt_offset Ben Widawsky
2013-07-04 12:20 ` Daniel Vetter
2013-07-03 21:45 ` [PATCH 4/6] drm/i915: Use gtt_space->start for stolen reservation Ben Widawsky
2013-07-04 12:23 ` Daniel Vetter
2013-07-03 21:45 ` [PATCH 5/6] drm/i915: Embed drm_mm_node in i915 gem obj Ben Widawsky
2013-07-04 12:27 ` Daniel Vetter
2013-07-03 21:45 ` [PATCH 6/6] drm: Optionally create mm blocks from top-to-bottom Ben Widawsky
2013-07-04 9:19 ` [PATCH 1/6] drm: pre allocate node for create_block David Herrmann
2013-07-04 20:03 ` Ben Widawsky [this message]
2013-07-04 9:22 ` David Herrmann
2013-07-04 20:14 ` [PATCH] [v3] " Ben Widawsky
2013-07-04 20:32 ` David Herrmann
2013-07-05 19:25 ` Daniel Vetter
2013-07-05 19:44 ` Ben Widawsky
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20130704200312.GA16758@bwidawsk.net \
--to=ben@bwidawsk.net \
--cc=dh.herrmann@gmail.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=intel-gfx@lists.freedesktop.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.