diff options
Diffstat (limited to 'drivers/accel/ivpu')
-rw-r--r-- | drivers/accel/ivpu/ivpu_drv.h | 1 | ||||
-rw-r--r-- | drivers/accel/ivpu/ivpu_gem.c | 8 | ||||
-rw-r--r-- | drivers/accel/ivpu/ivpu_hw_mtl.c | 20 |
3 files changed, 22 insertions, 7 deletions
diff --git a/drivers/accel/ivpu/ivpu_drv.h b/drivers/accel/ivpu/ivpu_drv.h index d3013fbd13b3..399dc5dcefd7 100644 --- a/drivers/accel/ivpu/ivpu_drv.h +++ b/drivers/accel/ivpu/ivpu_drv.h @@ -75,6 +75,7 @@ struct ivpu_wa_table { bool punit_disabled; bool clear_runtime_mem; bool d3hot_after_power_off; + bool interrupt_clear_with_0; }; struct ivpu_hw_info; diff --git a/drivers/accel/ivpu/ivpu_gem.c b/drivers/accel/ivpu/ivpu_gem.c index 52b339aefadc..9967fcfa27ec 100644 --- a/drivers/accel/ivpu/ivpu_gem.c +++ b/drivers/accel/ivpu/ivpu_gem.c @@ -173,6 +173,9 @@ static void internal_free_pages_locked(struct ivpu_bo *bo) { unsigned int i, npages = bo->base.size >> PAGE_SHIFT; + if (ivpu_bo_cache_mode(bo) != DRM_IVPU_BO_CACHED) + set_pages_array_wb(bo->pages, bo->base.size >> PAGE_SHIFT); + for (i = 0; i < npages; i++) put_page(bo->pages[i]); @@ -587,6 +590,11 @@ ivpu_bo_alloc_internal(struct ivpu_device *vdev, u64 vpu_addr, u64 size, u32 fla if (ivpu_bo_cache_mode(bo) != DRM_IVPU_BO_CACHED) drm_clflush_pages(bo->pages, bo->base.size >> PAGE_SHIFT); + if (bo->flags & DRM_IVPU_BO_WC) + set_pages_array_wc(bo->pages, bo->base.size >> PAGE_SHIFT); + else if (bo->flags & DRM_IVPU_BO_UNCACHED) + set_pages_array_uc(bo->pages, bo->base.size >> PAGE_SHIFT); + prot = ivpu_bo_pgprot(bo, PAGE_KERNEL); bo->kvaddr = vmap(bo->pages, bo->base.size >> PAGE_SHIFT, VM_MAP, prot); if (!bo->kvaddr) { diff --git a/drivers/accel/ivpu/ivpu_hw_mtl.c b/drivers/accel/ivpu/ivpu_hw_mtl.c index fef35422c6f0..2a5dd3a5dc46 100644 --- a/drivers/accel/ivpu/ivpu_hw_mtl.c +++ b/drivers/accel/ivpu/ivpu_hw_mtl.c @@ -101,6 +101,9 @@ static void ivpu_hw_wa_init(struct ivpu_device *vdev) vdev->wa.punit_disabled = ivpu_is_fpga(vdev); vdev->wa.clear_runtime_mem = false; vdev->wa.d3hot_after_power_off = true; + + if (ivpu_device_id(vdev) == PCI_DEVICE_ID_MTL && ivpu_revision(vdev) < 4) + vdev->wa.interrupt_clear_with_0 = true; } static void ivpu_hw_timeouts_init(struct ivpu_device *vdev) @@ -885,7 +888,7 @@ static void ivpu_hw_mtl_irq_disable(struct ivpu_device *vdev) REGB_WR32(MTL_BUTTRESS_GLOBAL_INT_MASK, 0x1); REGB_WR32(MTL_BUTTRESS_LOCAL_INT_MASK, BUTTRESS_IRQ_DISABLE_MASK); REGV_WR64(MTL_VPU_HOST_SS_ICB_ENABLE_0, 0x0ull); - REGB_WR32(MTL_VPU_HOST_SS_FW_SOC_IRQ_EN, 0x0); + REGV_WR32(MTL_VPU_HOST_SS_FW_SOC_IRQ_EN, 0x0); } static void ivpu_hw_mtl_irq_wdt_nce_handler(struct ivpu_device *vdev) @@ -973,12 +976,15 @@ static u32 ivpu_hw_mtl_irqb_handler(struct ivpu_device *vdev, int irq) schedule_recovery = true; } - /* - * Clear local interrupt status by writing 0 to all bits. - * This must be done after interrupts are cleared at the source. - * Writing 1 triggers an interrupt, so we can't perform read update write. - */ - REGB_WR32(MTL_BUTTRESS_INTERRUPT_STAT, 0x0); + /* This must be done after interrupts are cleared at the source. */ + if (IVPU_WA(interrupt_clear_with_0)) + /* + * Writing 1 triggers an interrupt, so we can't perform read update write. + * Clear local interrupt status by writing 0 to all bits. + */ + REGB_WR32(MTL_BUTTRESS_INTERRUPT_STAT, 0x0); + else + REGB_WR32(MTL_BUTTRESS_INTERRUPT_STAT, status); /* Re-enable global interrupt */ REGB_WR32(MTL_BUTTRESS_GLOBAL_INT_MASK, 0x0); |