diff options
Diffstat (limited to 'drivers/gpu/drm/vc4/vc4_irq.c')
| -rw-r--r-- | drivers/gpu/drm/vc4/vc4_irq.c | 76 |
1 files changed, 62 insertions, 14 deletions
diff --git a/drivers/gpu/drm/vc4/vc4_irq.c b/drivers/gpu/drm/vc4/vc4_irq.c index e226c24e543f..63e88f90eef7 100644 --- a/drivers/gpu/drm/vc4/vc4_irq.c +++ b/drivers/gpu/drm/vc4/vc4_irq.c @@ -45,15 +45,19 @@ * current job can make progress. */ +#include <linux/platform_device.h> + +#include <drm/drm_drv.h> +#include <drm/drm_print.h> + #include "vc4_drv.h" #include "vc4_regs.h" +#include "vc4_trace.h" #define V3D_DRIVER_IRQS (V3D_INT_OUTOMEM | \ V3D_INT_FLDONE | \ V3D_INT_FRDONE) -DECLARE_WAIT_QUEUE_HEAD(render_wait); - static void vc4_overflow_mem_work(struct work_struct *work) { @@ -73,7 +77,7 @@ vc4_overflow_mem_work(struct work_struct *work) bin_bo_slot = vc4_v3d_get_bin_slot(vc4); if (bin_bo_slot < 0) { - DRM_ERROR("Couldn't allocate binner overflow mem\n"); + drm_err(&vc4->base, "Couldn't allocate binner overflow mem\n"); goto complete; } @@ -100,7 +104,7 @@ vc4_overflow_mem_work(struct work_struct *work) } vc4->bin_alloc_overflow = BIT(bin_bo_slot); - V3D_WRITE(V3D_BPOA, bo->base.paddr + bin_bo_slot * vc4->bin_alloc_size); + V3D_WRITE(V3D_BPOA, bo->base.dma_addr + bin_bo_slot * vc4->bin_alloc_size); V3D_WRITE(V3D_BPOS, bo->base.base.size); V3D_WRITE(V3D_INTCTL, V3D_INT_OUTOMEM); V3D_WRITE(V3D_INTENA, V3D_INT_OUTOMEM); @@ -119,6 +123,8 @@ vc4_irq_finish_bin_job(struct drm_device *dev) if (!exec) return; + trace_vc4_bcl_end_irq(dev, exec->seqno); + vc4_move_job_to_render(dev, exec); next = vc4_first_bin_job(vc4); @@ -157,6 +163,8 @@ vc4_irq_finish_render_job(struct drm_device *dev) if (!exec) return; + trace_vc4_rcl_end_irq(dev, exec->seqno); + vc4->finished_seqno++; list_move_tail(&exec->head, &vc4->job_done_list); @@ -192,7 +200,7 @@ vc4_irq_finish_render_job(struct drm_device *dev) schedule_work(&vc4->job_done_work); } -irqreturn_t +static irqreturn_t vc4_irq(int irq, void *arg) { struct drm_device *dev = arg; @@ -234,8 +242,8 @@ vc4_irq(int irq, void *arg) return status; } -void -vc4_irq_preinstall(struct drm_device *dev) +static void +vc4_irq_prepare(struct drm_device *dev) { struct vc4_dev *vc4 = to_vc4_dev(dev); @@ -251,27 +259,31 @@ vc4_irq_preinstall(struct drm_device *dev) V3D_WRITE(V3D_INTCTL, V3D_DRIVER_IRQS); } -int -vc4_irq_postinstall(struct drm_device *dev) +void +vc4_irq_enable(struct drm_device *dev) { struct vc4_dev *vc4 = to_vc4_dev(dev); + if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + if (!vc4->v3d) - return 0; + return; /* Enable the render done interrupts. The out-of-memory interrupt is * enabled as soon as we have a binner BO allocated. */ V3D_WRITE(V3D_INTENA, V3D_INT_FLDONE | V3D_INT_FRDONE); - - return 0; } void -vc4_irq_uninstall(struct drm_device *dev) +vc4_irq_disable(struct drm_device *dev) { struct vc4_dev *vc4 = to_vc4_dev(dev); + if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + if (!vc4->v3d) return; @@ -282,17 +294,53 @@ vc4_irq_uninstall(struct drm_device *dev) V3D_WRITE(V3D_INTCTL, V3D_DRIVER_IRQS); /* Finish any interrupt handler still in flight. */ - disable_irq(dev->irq); + synchronize_irq(vc4->irq); cancel_work_sync(&vc4->overflow_mem_work); } +int vc4_irq_install(struct drm_device *dev, int irq) +{ + struct vc4_dev *vc4 = to_vc4_dev(dev); + int ret; + + if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + 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); + + if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + + vc4_irq_disable(dev); + free_irq(vc4->irq, dev); +} + /** Reinitializes interrupt registers when a GPU reset is performed. */ void vc4_irq_reset(struct drm_device *dev) { struct vc4_dev *vc4 = to_vc4_dev(dev); unsigned long irqflags; + if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + /* Acknowledge any stale IRQs. */ V3D_WRITE(V3D_INTCTL, V3D_DRIVER_IRQS); |
