[PATCH RFC 1/3] DRM: Armada: Add Armada DRM driver

Russell King - ARM Linux linux at arm.linux.org.uk
Sun Jun 30 09:41:51 EDT 2013


On Sun, Jun 30, 2013 at 02:04:56PM +0100, Russell King - ARM Linux wrote:
> On Sun, Jun 30, 2013 at 02:37:41PM +0200, Daniel Vetter wrote:
> > On Sat, Jun 29, 2013 at 11:53:22PM +0100, Russell King wrote:
> > > +		mutex_lock(&dev->struct_mutex);
> > > +		free = drm_mm_search_free(&priv->linear, size, align, 0);
> > > +		if (free)
> > > +			obj->linear = drm_mm_get_block(free, size, align);
> > > +		mutex_unlock(&dev->struct_mutex);
> > 
> > The two-stage search_free+get_block drm_mm interface is something I'd like
> > to remove since it' complicates the interface for no gain. And the
> > preallocation trick for atomic contexts is pretty racy as-is. Can you
> > please convert this over to the insert_node interfaces which take a
> > preallocate drm_mm_node?
> 
> Yes and no.  This is only racy if it is callable from atomic contexts,
> which the above isn't, because it takes a mutex, and the above is the
> only place which allocations against that pool are done.  Mutexes can't
> be taken in atomic contexts.  Plus it's using the non-atomic drm_mm_*
> interfaces.
> 
> However, the insert_node interfaces appear not to solve any kind of race.
> All they do is allow the kmalloc to be moved out of this region into
> the user of this code sequence, while offering no additional locking or
> safety.  So the mutex lock around a call to drm_mm_insert_node*() is
> still required.
> 
> As the kmalloc() happens beneath the mutex lock, another thread can't race
> with an allocation in the above code anyway.  The *only* reason I'll change
> this is that it is nicer to the system not to hold locks while allocating
> memory.

Err.  There's bugs here in the other drivers such as i915 which follow
your suggestion.  The problem is this:

Every time they allocate using drm_mm_insert_node(), they kmalloc a new
struct drm_mm_node for this function to fill in and attach.

When they've done with the allocation, they call drm_mm_put_block().
This places the node onto the mm's unused_nodes list provided we don't
already have MM_UNUSED_TARGET nodes on that list.

So, we end up filling up the unused nodes list to MM_UNUSED_TARGET,
at which point we then start freeing any further nodes - and with no
way to pull these off that list, they all just sit there not being
used.

The only function which takes nodes off that list is drm_mm_kmalloc(),
which is declared statically, and so isn't available to drivers.

Are drivers which use the drm_mm_insert_node() function expected to
also use drm_mm_remove_node(), kfreeing the node after that call,
rather than using drm_mm_put_block() ?

Either way, I think someone needs to fix the other drivers and Cc those
patches to Stable...



More information about the linux-arm-kernel mailing list