drm/nouveau: use system_wq instead of dev_priv->wq
authorTejun Heo <tj@kernel.org>
Wed, 26 Jan 2011 16:49:18 +0000 (17:49 +0100)
committerBen Skeggs <bskeggs@redhat.com>
Thu, 24 Feb 2011 20:44:36 +0000 (06:44 +1000)
With cmwq, there's no reason for nouveau to use a dedicated workqueue.
Drop dev_priv->wq and use system_wq instead.  Each work item is sync
flushed when the containing structure is unregistered/destroyed.

Note that this change also makes sure that nv50_gpio_handler is not
freed while the contained work item is still running.

Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: David Airlie <airlied@linux.ie>
Cc: dri-devel@lists.freedesktop.org
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/nouveau_drv.h
drivers/gpu/drm/nouveau/nouveau_state.c
drivers/gpu/drm/nouveau/nv50_display.c
drivers/gpu/drm/nouveau/nv50_gpio.c

index 1c6279f..2e3d7fb 100644 (file)
@@ -652,7 +652,6 @@ struct drm_nouveau_private {
        /* interrupt handling */
        void (*irq_handler[32])(struct drm_device *);
        bool msi_enabled;
-       struct workqueue_struct *wq;
        struct work_struct irq_work;
 
        struct list_head vbl_waiting;
index 2148d01..805c0b3 100644 (file)
@@ -929,12 +929,6 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
        NV_DEBUG(dev, "vendor: 0x%X device: 0x%X class: 0x%X\n",
                 dev->pci_vendor, dev->pci_device, dev->pdev->class);
 
-       dev_priv->wq = create_workqueue("nouveau");
-       if (!dev_priv->wq) {
-               ret = -EINVAL;
-               goto err_priv;
-       }
-
        /* resource 0 is mmio regs */
        /* resource 1 is linear FB */
        /* resource 2 is RAMIN (mmio regs + 0x1000000) */
@@ -947,7 +941,7 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
                NV_ERROR(dev, "Unable to initialize the mmio mapping. "
                         "Please report your setup to " DRIVER_EMAIL "\n");
                ret = -EINVAL;
-               goto err_wq;
+               goto err_priv;
        }
        NV_DEBUG(dev, "regs mapped ok at 0x%llx\n",
                                        (unsigned long long)mmio_start_offs);
@@ -1054,8 +1048,6 @@ err_ramin:
        iounmap(dev_priv->ramin);
 err_mmio:
        iounmap(dev_priv->mmio);
-err_wq:
-       destroy_workqueue(dev_priv->wq);
 err_priv:
        kfree(dev_priv);
        dev->dev_private = NULL;
index 5096f2f..a804a35 100644 (file)
@@ -345,12 +345,15 @@ int nv50_display_create(struct drm_device *dev)
 void
 nv50_display_destroy(struct drm_device *dev)
 {
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+
        NV_DEBUG_KMS(dev, "\n");
 
        drm_mode_config_cleanup(dev);
 
        nv50_display_disable(dev);
        nouveau_irq_unregister(dev, 26);
+       flush_work_sync(&dev_priv->irq_work);
 }
 
 static u16
@@ -836,7 +839,7 @@ nv50_display_isr(struct drm_device *dev)
                if (clock) {
                        nv_wr32(dev, NV03_PMC_INTR_EN_0, 0);
                        if (!work_pending(&dev_priv->irq_work))
-                               queue_work(dev_priv->wq, &dev_priv->irq_work);
+                               schedule_work(&dev_priv->irq_work);
                        delayed |= clock;
                        intr1 &= ~clock;
                }
index 1710c08..d4f4206 100644 (file)
@@ -137,6 +137,7 @@ nv50_gpio_irq_unregister(struct drm_device *dev, enum dcb_gpio_tag tag,
        struct nv50_gpio_priv *priv = pgpio->priv;
        struct nv50_gpio_handler *gpioh, *tmp;
        struct dcb_gpio_entry *gpio;
+       LIST_HEAD(tofree);
        unsigned long flags;
 
        gpio = nouveau_bios_gpio_entry(dev, tag);
@@ -149,10 +150,14 @@ nv50_gpio_irq_unregister(struct drm_device *dev, enum dcb_gpio_tag tag,
                    gpioh->handler != handler ||
                    gpioh->data != data)
                        continue;
-               list_del(&gpioh->head);
-               kfree(gpioh);
+               list_move(&gpioh->head, &tofree);
        }
        spin_unlock_irqrestore(&priv->lock, flags);
+
+       list_for_each_entry_safe(gpioh, tmp, &tofree, head) {
+               flush_work_sync(&gpioh->work);
+               kfree(gpioh);
+       }
 }
 
 bool
@@ -291,7 +296,7 @@ nv50_gpio_isr(struct drm_device *dev)
                        continue;
                gpioh->inhibit = true;
 
-               queue_work(dev_priv->wq, &gpioh->work);
+               schedule_work(&gpioh->work);
        }
        spin_unlock(&priv->lock);
 }