drm/nouveau: use system_wq instead of dev_priv->wq
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>
This commit is contained in:
@@ -652,7 +652,6 @@ struct drm_nouveau_private {
|
|||||||
/* interrupt handling */
|
/* interrupt handling */
|
||||||
void (*irq_handler[32])(struct drm_device *);
|
void (*irq_handler[32])(struct drm_device *);
|
||||||
bool msi_enabled;
|
bool msi_enabled;
|
||||||
struct workqueue_struct *wq;
|
|
||||||
struct work_struct irq_work;
|
struct work_struct irq_work;
|
||||||
|
|
||||||
struct list_head vbl_waiting;
|
struct list_head vbl_waiting;
|
||||||
|
@@ -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",
|
NV_DEBUG(dev, "vendor: 0x%X device: 0x%X class: 0x%X\n",
|
||||||
dev->pci_vendor, dev->pci_device, dev->pdev->class);
|
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 0 is mmio regs */
|
||||||
/* resource 1 is linear FB */
|
/* resource 1 is linear FB */
|
||||||
/* resource 2 is RAMIN (mmio regs + 0x1000000) */
|
/* 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. "
|
NV_ERROR(dev, "Unable to initialize the mmio mapping. "
|
||||||
"Please report your setup to " DRIVER_EMAIL "\n");
|
"Please report your setup to " DRIVER_EMAIL "\n");
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto err_wq;
|
goto err_priv;
|
||||||
}
|
}
|
||||||
NV_DEBUG(dev, "regs mapped ok at 0x%llx\n",
|
NV_DEBUG(dev, "regs mapped ok at 0x%llx\n",
|
||||||
(unsigned long long)mmio_start_offs);
|
(unsigned long long)mmio_start_offs);
|
||||||
@@ -1054,8 +1048,6 @@ err_ramin:
|
|||||||
iounmap(dev_priv->ramin);
|
iounmap(dev_priv->ramin);
|
||||||
err_mmio:
|
err_mmio:
|
||||||
iounmap(dev_priv->mmio);
|
iounmap(dev_priv->mmio);
|
||||||
err_wq:
|
|
||||||
destroy_workqueue(dev_priv->wq);
|
|
||||||
err_priv:
|
err_priv:
|
||||||
kfree(dev_priv);
|
kfree(dev_priv);
|
||||||
dev->dev_private = NULL;
|
dev->dev_private = NULL;
|
||||||
|
@@ -345,12 +345,15 @@ int nv50_display_create(struct drm_device *dev)
|
|||||||
void
|
void
|
||||||
nv50_display_destroy(struct drm_device *dev)
|
nv50_display_destroy(struct drm_device *dev)
|
||||||
{
|
{
|
||||||
|
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||||
|
|
||||||
NV_DEBUG_KMS(dev, "\n");
|
NV_DEBUG_KMS(dev, "\n");
|
||||||
|
|
||||||
drm_mode_config_cleanup(dev);
|
drm_mode_config_cleanup(dev);
|
||||||
|
|
||||||
nv50_display_disable(dev);
|
nv50_display_disable(dev);
|
||||||
nouveau_irq_unregister(dev, 26);
|
nouveau_irq_unregister(dev, 26);
|
||||||
|
flush_work_sync(&dev_priv->irq_work);
|
||||||
}
|
}
|
||||||
|
|
||||||
static u16
|
static u16
|
||||||
@@ -836,7 +839,7 @@ nv50_display_isr(struct drm_device *dev)
|
|||||||
if (clock) {
|
if (clock) {
|
||||||
nv_wr32(dev, NV03_PMC_INTR_EN_0, 0);
|
nv_wr32(dev, NV03_PMC_INTR_EN_0, 0);
|
||||||
if (!work_pending(&dev_priv->irq_work))
|
if (!work_pending(&dev_priv->irq_work))
|
||||||
queue_work(dev_priv->wq, &dev_priv->irq_work);
|
schedule_work(&dev_priv->irq_work);
|
||||||
delayed |= clock;
|
delayed |= clock;
|
||||||
intr1 &= ~clock;
|
intr1 &= ~clock;
|
||||||
}
|
}
|
||||||
|
@@ -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_priv *priv = pgpio->priv;
|
||||||
struct nv50_gpio_handler *gpioh, *tmp;
|
struct nv50_gpio_handler *gpioh, *tmp;
|
||||||
struct dcb_gpio_entry *gpio;
|
struct dcb_gpio_entry *gpio;
|
||||||
|
LIST_HEAD(tofree);
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
gpio = nouveau_bios_gpio_entry(dev, tag);
|
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->handler != handler ||
|
||||||
gpioh->data != data)
|
gpioh->data != data)
|
||||||
continue;
|
continue;
|
||||||
list_del(&gpioh->head);
|
list_move(&gpioh->head, &tofree);
|
||||||
kfree(gpioh);
|
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&priv->lock, flags);
|
spin_unlock_irqrestore(&priv->lock, flags);
|
||||||
|
|
||||||
|
list_for_each_entry_safe(gpioh, tmp, &tofree, head) {
|
||||||
|
flush_work_sync(&gpioh->work);
|
||||||
|
kfree(gpioh);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@@ -291,7 +296,7 @@ nv50_gpio_isr(struct drm_device *dev)
|
|||||||
continue;
|
continue;
|
||||||
gpioh->inhibit = true;
|
gpioh->inhibit = true;
|
||||||
|
|
||||||
queue_work(dev_priv->wq, &gpioh->work);
|
schedule_work(&gpioh->work);
|
||||||
}
|
}
|
||||||
spin_unlock(&priv->lock);
|
spin_unlock(&priv->lock);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user