From 3945e47543863385b54d94c94b023ee7ca9df972 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Mon, 18 Oct 2010 03:53:39 +0200 Subject: drm/nouveau: Refactor context destruction to avoid a lock ordering issue. The destroy_context() engine hooks call gpuobj management functions to release the channel resources, these functions use HARDIRQ-unsafe locks whereas destroy_context() is called with the HARDIRQ-safe context_switch_lock held, that's a lock ordering violation. Push the engine-specific channel destruction logic into destroy_context() and let the hardware-specific code lock and unlock when it's actually needed. Change the engine destruction order to avoid a race in the small gap between pgraph and pfifo context uninitialization. Reported-by: Marcin Slusarz Signed-off-by: Francisco Jerez Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nv20_graph.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/nouveau/nv20_graph.c') diff --git a/drivers/gpu/drm/nouveau/nv20_graph.c b/drivers/gpu/drm/nouveau/nv20_graph.c index 12ab9cd..8a04020 100644 --- a/drivers/gpu/drm/nouveau/nv20_graph.c +++ b/drivers/gpu/drm/nouveau/nv20_graph.c @@ -425,9 +425,21 @@ nv20_graph_destroy_context(struct nouveau_channel *chan) struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; + unsigned long flags; - nouveau_gpuobj_ref(NULL, &chan->ramin_grctx); + spin_lock_irqsave(&dev_priv->context_switch_lock, flags); + pgraph->fifo_access(dev, false); + + /* Unload the context if it's the currently active one */ + if (pgraph->channel(dev) == chan) + pgraph->unload_context(dev); + + pgraph->fifo_access(dev, true); + spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + + /* Free the context resources */ nv_wo32(pgraph->ctx_table, chan->id * 4, 0); + nouveau_gpuobj_ref(NULL, &chan->ramin_grctx); } int -- cgit v1.1