/** * DOC: Interrupt management for the V3D engine * * We have an interrupt status register (V3D_INTCTL) which reports * interrupts, and where writing 1 bits clears those interrupts. * There are also a pair of interrupt registers * (V3D_INTENA/V3D_INTDIS) where writing a 1 to their bits enables or * disables that specific interrupt, and 0s written are ignored * (reading either one returns the set of enabled interrupts). * * When we take a binning flush done interrupt, we need to submit the * next frame for binning and move the finished frame to the render * thread. * * When we take a render frame interrupt, we need to wake the * processes waiting for some frame to be done, and get the next frame * submitted ASAP (so the hardware doesn't sit idle when there's work * to do). * * When we take the binner out of memory interrupt, we need to * allocate some new memory and pass it to the binner so that the * current job can make progress.
*/
if (vc4->bin_alloc_overflow) { /* If we had overflow memory allocated previously, * then that chunk will free when the current bin job * is done. If we don't have a bin job running, then * the chunk will be done whenever the list of render * jobs has drained.
*/
exec = vc4_first_bin_job(vc4); if (!exec)
exec = vc4_last_render_job(vc4); if (exec) {
exec->bin_slots |= vc4->bin_alloc_overflow;
} else { /* There's nothing queued in the hardware, so * the old slot is free immediately.
*/
vc4->bin_alloc_used &= ~vc4->bin_alloc_overflow;
}
}
vc4->bin_alloc_overflow = BIT(bin_bo_slot);
vc4_move_job_to_render(dev, exec);
next = vc4_first_bin_job(vc4);
/* Only submit the next job in the bin list if it matches the perfmon * attached to the one that just finished (or if both jobs don't have * perfmon attached to them).
*/ if (next && next->perfmon == exec->perfmon)
vc4_submit_next_bin_job(dev);
}
/* Only stop the perfmon if following jobs in the queue don't expect it * to be enabled.
*/ if (exec->perfmon && !nextrender &&
(!nextbin || nextbin->perfmon != exec->perfmon))
vc4_perfmon_stop(vc4, exec->perfmon, true);
/* If there's a render job waiting, start it. If this is not the case * we may have to unblock the binner if it's been stalled because of * perfmon (this can be checked by comparing the perfmon attached to * the finished renderjob to the one attached to the next bin job: if * they don't match, this means the binner is stalled and should be * restarted).
*/ if (nextrender)
vc4_submit_next_render_job(dev); elseif (nextbin && nextbin->perfmon != exec->perfmon)
vc4_submit_next_bin_job(dev);
if (exec->fence) {
dma_fence_signal_locked(exec->fence);
dma_fence_put(exec->fence);
exec->fence = NULL;
}
/* Acknowledge the interrupts we're handling here. The binner * last flush / render frame done interrupt will be cleared, * while OUTOMEM will stay high until the underlying cause is * cleared.
*/
V3D_WRITE(V3D_INTCTL, intctl);
if (intctl & V3D_INT_OUTOMEM) { /* Disable OUTOMEM until the work is done. */
V3D_WRITE(V3D_INTDIS, V3D_INT_OUTOMEM);
schedule_work(&vc4->overflow_mem_work);
status = IRQ_HANDLED;
}
if (intctl & V3D_INT_FLDONE) {
spin_lock(&vc4->job_lock);
vc4_irq_finish_bin_job(dev);
spin_unlock(&vc4->job_lock);
status = IRQ_HANDLED;
}
if (intctl & V3D_INT_FRDONE) {
spin_lock(&vc4->job_lock);
vc4_irq_finish_render_job(dev);
spin_unlock(&vc4->job_lock);
status = IRQ_HANDLED;
}
/* 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);
}
/** 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); unsignedlong irqflags;
if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) return;
/* Acknowledge any stale IRQs. */
V3D_WRITE(V3D_INTCTL, V3D_DRIVER_IRQS);
/* * Turn all our interrupts on. Binner out of memory is the * only one we expect to trigger at this point, since we've * just come from poweron and haven't supplied any overflow * memory yet.
*/
V3D_WRITE(V3D_INTENA, V3D_DRIVER_IRQS);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.