Commit 5226711e authored by Thomas Zimmermann's avatar Thomas Zimmermann

drm/vc4: Convert to Linux IRQ interfaces

Drop the DRM IRQ midlayer in favor of Linux IRQ interfaces. DRM's
IRQ helpers are mostly useful for UMS drivers. Modern KMS drivers
don't benefit from using it.

DRM IRQ callbacks are now being called directly or inlined.

Calls to platform_get_irq() can fail with a negative errno code.
Abort initialization in this case. The DRM IRQ midlayer does not
handle this case correctly.
Signed-off-by: default avatarThomas Zimmermann <tzimmermann@suse.de>
Acked-by: default avatarSam Ravnborg <sam@ravnborg.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20210803090704.32152-13-tzimmermann@suse.de
parent b6366814
...@@ -168,10 +168,6 @@ static struct drm_driver vc4_drm_driver = { ...@@ -168,10 +168,6 @@ static struct drm_driver vc4_drm_driver = {
DRIVER_SYNCOBJ), DRIVER_SYNCOBJ),
.open = vc4_open, .open = vc4_open,
.postclose = vc4_close, .postclose = vc4_close,
.irq_handler = vc4_irq,
.irq_preinstall = vc4_irq_preinstall,
.irq_postinstall = vc4_irq_postinstall,
.irq_uninstall = vc4_irq_uninstall,
#if defined(CONFIG_DEBUG_FS) #if defined(CONFIG_DEBUG_FS)
.debugfs_init = vc4_debugfs_init, .debugfs_init = vc4_debugfs_init,
......
...@@ -74,6 +74,8 @@ struct vc4_perfmon { ...@@ -74,6 +74,8 @@ struct vc4_perfmon {
struct vc4_dev { struct vc4_dev {
struct drm_device base; struct drm_device base;
unsigned int irq;
struct vc4_hvs *hvs; struct vc4_hvs *hvs;
struct vc4_v3d *v3d; struct vc4_v3d *v3d;
struct vc4_dpi *dpi; struct vc4_dpi *dpi;
...@@ -895,9 +897,9 @@ extern struct platform_driver vc4_vec_driver; ...@@ -895,9 +897,9 @@ extern struct platform_driver vc4_vec_driver;
extern struct platform_driver vc4_txp_driver; extern struct platform_driver vc4_txp_driver;
/* vc4_irq.c */ /* vc4_irq.c */
irqreturn_t vc4_irq(int irq, void *arg); void vc4_irq_enable(struct drm_device *dev);
void vc4_irq_preinstall(struct drm_device *dev); void vc4_irq_disable(struct drm_device *dev);
int vc4_irq_postinstall(struct drm_device *dev); int vc4_irq_install(struct drm_device *dev, int irq);
void vc4_irq_uninstall(struct drm_device *dev); void vc4_irq_uninstall(struct drm_device *dev);
void vc4_irq_reset(struct drm_device *dev); void vc4_irq_reset(struct drm_device *dev);
......
...@@ -45,6 +45,10 @@ ...@@ -45,6 +45,10 @@
* current job can make progress. * current job can make progress.
*/ */
#include <linux/platform_device.h>
#include <drm/drm_drv.h>
#include "vc4_drv.h" #include "vc4_drv.h"
#include "vc4_regs.h" #include "vc4_regs.h"
...@@ -192,7 +196,7 @@ vc4_irq_finish_render_job(struct drm_device *dev) ...@@ -192,7 +196,7 @@ vc4_irq_finish_render_job(struct drm_device *dev)
schedule_work(&vc4->job_done_work); schedule_work(&vc4->job_done_work);
} }
irqreturn_t static irqreturn_t
vc4_irq(int irq, void *arg) vc4_irq(int irq, void *arg)
{ {
struct drm_device *dev = arg; struct drm_device *dev = arg;
...@@ -234,8 +238,8 @@ vc4_irq(int irq, void *arg) ...@@ -234,8 +238,8 @@ vc4_irq(int irq, void *arg)
return status; return status;
} }
void static void
vc4_irq_preinstall(struct drm_device *dev) vc4_irq_prepare(struct drm_device *dev)
{ {
struct vc4_dev *vc4 = to_vc4_dev(dev); struct vc4_dev *vc4 = to_vc4_dev(dev);
...@@ -251,24 +255,22 @@ vc4_irq_preinstall(struct drm_device *dev) ...@@ -251,24 +255,22 @@ vc4_irq_preinstall(struct drm_device *dev)
V3D_WRITE(V3D_INTCTL, V3D_DRIVER_IRQS); V3D_WRITE(V3D_INTCTL, V3D_DRIVER_IRQS);
} }
int void
vc4_irq_postinstall(struct drm_device *dev) vc4_irq_enable(struct drm_device *dev)
{ {
struct vc4_dev *vc4 = to_vc4_dev(dev); struct vc4_dev *vc4 = to_vc4_dev(dev);
if (!vc4->v3d) if (!vc4->v3d)
return 0; return;
/* Enable the render done interrupts. The out-of-memory interrupt is /* Enable the render done interrupts. The out-of-memory interrupt is
* enabled as soon as we have a binner BO allocated. * enabled as soon as we have a binner BO allocated.
*/ */
V3D_WRITE(V3D_INTENA, V3D_INT_FLDONE | V3D_INT_FRDONE); V3D_WRITE(V3D_INTENA, V3D_INT_FLDONE | V3D_INT_FRDONE);
return 0;
} }
void void
vc4_irq_uninstall(struct drm_device *dev) vc4_irq_disable(struct drm_device *dev)
{ {
struct vc4_dev *vc4 = to_vc4_dev(dev); struct vc4_dev *vc4 = to_vc4_dev(dev);
...@@ -282,11 +284,37 @@ vc4_irq_uninstall(struct drm_device *dev) ...@@ -282,11 +284,37 @@ vc4_irq_uninstall(struct drm_device *dev)
V3D_WRITE(V3D_INTCTL, V3D_DRIVER_IRQS); V3D_WRITE(V3D_INTCTL, V3D_DRIVER_IRQS);
/* Finish any interrupt handler still in flight. */ /* Finish any interrupt handler still in flight. */
disable_irq(dev->irq); disable_irq(vc4->irq);
cancel_work_sync(&vc4->overflow_mem_work); cancel_work_sync(&vc4->overflow_mem_work);
} }
int vc4_irq_install(struct drm_device *dev, int irq)
{
int ret;
if (irq == IRQ_NOTCONNECTED)
return -ENOTCONN;
vc4_irq_prepare(dev);
ret = request_irq(irq, vc4_irq, 0, dev->driver->name, dev);
if (ret)
return ret;
vc4_irq_enable(dev);
return 0;
}
void vc4_irq_uninstall(struct drm_device *dev)
{
struct vc4_dev *vc4 = to_vc4_dev(dev);
vc4_irq_disable(dev);
free_irq(vc4->irq, dev);
}
/** Reinitializes interrupt registers when a GPU reset is performed. */ /** Reinitializes interrupt registers when a GPU reset is performed. */
void vc4_irq_reset(struct drm_device *dev) void vc4_irq_reset(struct drm_device *dev)
{ {
......
...@@ -10,8 +10,6 @@ ...@@ -10,8 +10,6 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <drm/drm_irq.h>
#include "vc4_drv.h" #include "vc4_drv.h"
#include "vc4_regs.h" #include "vc4_regs.h"
...@@ -361,7 +359,7 @@ static int vc4_v3d_runtime_suspend(struct device *dev) ...@@ -361,7 +359,7 @@ static int vc4_v3d_runtime_suspend(struct device *dev)
struct vc4_v3d *v3d = dev_get_drvdata(dev); struct vc4_v3d *v3d = dev_get_drvdata(dev);
struct vc4_dev *vc4 = v3d->vc4; struct vc4_dev *vc4 = v3d->vc4;
vc4_irq_uninstall(&vc4->base); vc4_irq_disable(&vc4->base);
clk_disable_unprepare(v3d->clk); clk_disable_unprepare(v3d->clk);
...@@ -381,8 +379,8 @@ static int vc4_v3d_runtime_resume(struct device *dev) ...@@ -381,8 +379,8 @@ static int vc4_v3d_runtime_resume(struct device *dev)
vc4_v3d_init_hw(&vc4->base); vc4_v3d_init_hw(&vc4->base);
/* We disabled the IRQ as part of vc4_irq_uninstall in suspend. */ /* We disabled the IRQ as part of vc4_irq_uninstall in suspend. */
enable_irq(vc4->base.irq); enable_irq(vc4->irq);
vc4_irq_postinstall(&vc4->base); vc4_irq_enable(&vc4->base);
return 0; return 0;
} }
...@@ -448,7 +446,12 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data) ...@@ -448,7 +446,12 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data)
vc4_v3d_init_hw(drm); vc4_v3d_init_hw(drm);
ret = drm_irq_install(drm, platform_get_irq(pdev, 0)); ret = platform_get_irq(pdev, 0);
if (ret < 0)
return ret;
vc4->irq = ret;
ret = vc4_irq_install(drm, vc4->irq);
if (ret) { if (ret) {
DRM_ERROR("Failed to install IRQ handler\n"); DRM_ERROR("Failed to install IRQ handler\n");
return ret; return ret;
...@@ -473,7 +476,7 @@ static void vc4_v3d_unbind(struct device *dev, struct device *master, ...@@ -473,7 +476,7 @@ static void vc4_v3d_unbind(struct device *dev, struct device *master,
pm_runtime_disable(dev); pm_runtime_disable(dev);
drm_irq_uninstall(drm); vc4_irq_uninstall(drm);
/* Disable the binner's overflow memory address, so the next /* Disable the binner's overflow memory address, so the next
* driver probe (if any) doesn't try to reuse our old * driver probe (if any) doesn't try to reuse our old
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment