Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

accel/ivpu: Clear specific interrupt status bits on C0

MTL C0 stepping fixed issue related to butrress interrupt status clearing,
to clear an interrupt status it is required to write 1 to specific
status bit field. This allows to execute read, modify and write routine.

Writing 0 will not clear the interrupt and will cause interrupt storm.

Fixes: 35b137630f08 ("accel/ivpu: Introduce a new DRM driver for Intel VPU")
Cc: stable@vger.kernel.org # 6.3.x
Signed-off-by: Karol Wachowski <karol.wachowski@linux.intel.com>
Reviewed-by: Jacek Lawrynowicz <jacek.lawrynowicz@linux.intel.com>
Signed-off-by: Stanislaw Gruszka <stanislaw.gruszka@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20230703080725.2065635-2-stanislaw.gruszka@linux.intel.com

authored by

Karol Wachowski and committed by
Stanislaw Gruszka
7f34e01f 020b527b

+13 -6
+1
drivers/accel/ivpu/ivpu_drv.h
··· 75 75 bool punit_disabled; 76 76 bool clear_runtime_mem; 77 77 bool d3hot_after_power_off; 78 + bool interrupt_clear_with_0; 78 79 }; 79 80 80 81 struct ivpu_hw_info;
+12 -6
drivers/accel/ivpu/ivpu_hw_mtl.c
··· 101 101 vdev->wa.punit_disabled = ivpu_is_fpga(vdev); 102 102 vdev->wa.clear_runtime_mem = false; 103 103 vdev->wa.d3hot_after_power_off = true; 104 + 105 + if (ivpu_device_id(vdev) == PCI_DEVICE_ID_MTL && ivpu_revision(vdev) < 4) 106 + vdev->wa.interrupt_clear_with_0 = true; 104 107 } 105 108 106 109 static void ivpu_hw_timeouts_init(struct ivpu_device *vdev) ··· 976 973 schedule_recovery = true; 977 974 } 978 975 979 - /* 980 - * Clear local interrupt status by writing 0 to all bits. 981 - * This must be done after interrupts are cleared at the source. 982 - * Writing 1 triggers an interrupt, so we can't perform read update write. 983 - */ 984 - REGB_WR32(MTL_BUTTRESS_INTERRUPT_STAT, 0x0); 976 + /* This must be done after interrupts are cleared at the source. */ 977 + if (IVPU_WA(interrupt_clear_with_0)) 978 + /* 979 + * Writing 1 triggers an interrupt, so we can't perform read update write. 980 + * Clear local interrupt status by writing 0 to all bits. 981 + */ 982 + REGB_WR32(MTL_BUTTRESS_INTERRUPT_STAT, 0x0); 983 + else 984 + REGB_WR32(MTL_BUTTRESS_INTERRUPT_STAT, status); 985 985 986 986 /* Re-enable global interrupt */ 987 987 REGB_WR32(MTL_BUTTRESS_GLOBAL_INT_MASK, 0x0);