Skip to content

Commit 4480912

Browse files
kwachowsjlawryno
authored andcommitted
accel/ivpu: Move parts of MMU event IRQ handling to thread handler
To prevent looping infinitely in MMU event handler we stop generating new events by removing 'R' (record) bit from context descriptor, but to ensure this change has effect KMD has to perform configuration invalidation followed by sync command. Because of that move parts of the interrupt handler that can take longer to a thread not to block in interrupt handler for too long. This includes: * disabling event queue for the time KMD updates MMU event queue consumer to ensure proper synchronization between MMU and KMD * removal of 'R' (record) bit from context descriptor to ensure no more faults are recorded until that context is destroyed Signed-off-by: Karol Wachowski <karol.wachowski@intel.com> Signed-off-by: Maciej Falkowski <maciej.falkowski@linux.intel.com> Reviewed-by: Jacek Lawrynowicz <jacek.lawrynowicz@linux.intel.com> Signed-off-by: Jacek Lawrynowicz <jacek.lawrynowicz@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20250107173238.381120-8-maciej.falkowski@linux.intel.com
1 parent 0240fa1 commit 4480912

File tree

3 files changed

+69
-33
lines changed

3 files changed

+69
-33
lines changed

drivers/accel/ivpu/ivpu_job.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "ivpu_ipc.h"
1818
#include "ivpu_job.h"
1919
#include "ivpu_jsm_msg.h"
20+
#include "ivpu_mmu.h"
2021
#include "ivpu_pm.h"
2122
#include "ivpu_trace.h"
2223
#include "vpu_boot_api.h"
@@ -366,13 +367,17 @@ void ivpu_context_abort_locked(struct ivpu_file_priv *file_priv)
366367
unsigned long cmdq_id;
367368

368369
lockdep_assert_held(&file_priv->lock);
370+
ivpu_dbg(vdev, JOB, "Context ID: %u abort\n", file_priv->ctx.id);
369371

370372
xa_for_each(&file_priv->cmdq_xa, cmdq_id, cmdq)
371373
ivpu_cmdq_unregister(file_priv, cmdq);
372374

373375
if (vdev->fw->sched_mode == VPU_SCHEDULING_MODE_OS)
374376
ivpu_jsm_context_release(vdev, file_priv->ctx.id);
375377

378+
ivpu_mmu_disable_ssid_events(vdev, file_priv->ctx.id);
379+
ivpu_mmu_discard_events(vdev);
380+
376381
file_priv->aborted = true;
377382
}
378383

@@ -939,8 +944,8 @@ void ivpu_context_abort_work_fn(struct work_struct *work)
939944
{
940945
struct ivpu_device *vdev = container_of(work, struct ivpu_device, context_abort_work);
941946
struct ivpu_file_priv *file_priv;
942-
unsigned long ctx_id;
943947
struct ivpu_job *job;
948+
unsigned long ctx_id;
944949
unsigned long id;
945950

946951
mutex_lock(&vdev->context_list_lock);

drivers/accel/ivpu/ivpu_mmu.c

Lines changed: 61 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@
2020
#define IVPU_MMU_REG_CR0 0x00200020u
2121
#define IVPU_MMU_REG_CR0ACK 0x00200024u
2222
#define IVPU_MMU_REG_CR0ACK_VAL_MASK GENMASK(31, 0)
23+
#define IVPU_MMU_REG_CR0_ATSCHK_MASK BIT(4)
24+
#define IVPU_MMU_REG_CR0_CMDQEN_MASK BIT(3)
25+
#define IVPU_MMU_REG_CR0_EVTQEN_MASK BIT(2)
26+
#define IVPU_MMU_REG_CR0_PRIQEN_MASK BIT(1)
27+
#define IVPU_MMU_REG_CR0_SMMUEN_MASK BIT(0)
28+
2329
#define IVPU_MMU_REG_CR1 0x00200028u
2430
#define IVPU_MMU_REG_CR2 0x0020002cu
2531
#define IVPU_MMU_REG_IRQ_CTRL 0x00200050u
@@ -141,12 +147,6 @@
141147
#define IVPU_MMU_IRQ_EVTQ_EN BIT(2)
142148
#define IVPU_MMU_IRQ_GERROR_EN BIT(0)
143149

144-
#define IVPU_MMU_CR0_ATSCHK BIT(4)
145-
#define IVPU_MMU_CR0_CMDQEN BIT(3)
146-
#define IVPU_MMU_CR0_EVTQEN BIT(2)
147-
#define IVPU_MMU_CR0_PRIQEN BIT(1)
148-
#define IVPU_MMU_CR0_SMMUEN BIT(0)
149-
150150
#define IVPU_MMU_CR1_TABLE_SH GENMASK(11, 10)
151151
#define IVPU_MMU_CR1_TABLE_OC GENMASK(9, 8)
152152
#define IVPU_MMU_CR1_TABLE_IC GENMASK(7, 6)
@@ -596,7 +596,7 @@ static int ivpu_mmu_reset(struct ivpu_device *vdev)
596596
REGV_WR32(IVPU_MMU_REG_CMDQ_PROD, 0);
597597
REGV_WR32(IVPU_MMU_REG_CMDQ_CONS, 0);
598598

599-
val = IVPU_MMU_CR0_CMDQEN;
599+
val = REG_SET_FLD(IVPU_MMU_REG_CR0, CMDQEN, 0);
600600
ret = ivpu_mmu_reg_write_cr0(vdev, val);
601601
if (ret)
602602
return ret;
@@ -617,12 +617,12 @@ static int ivpu_mmu_reset(struct ivpu_device *vdev)
617617
REGV_WR32(IVPU_MMU_REG_EVTQ_PROD_SEC, 0);
618618
REGV_WR32(IVPU_MMU_REG_EVTQ_CONS_SEC, 0);
619619

620-
val |= IVPU_MMU_CR0_EVTQEN;
620+
val = REG_SET_FLD(IVPU_MMU_REG_CR0, EVTQEN, val);
621621
ret = ivpu_mmu_reg_write_cr0(vdev, val);
622622
if (ret)
623623
return ret;
624624

625-
val |= IVPU_MMU_CR0_ATSCHK;
625+
val = REG_SET_FLD(IVPU_MMU_REG_CR0, ATSCHK, val);
626626
ret = ivpu_mmu_reg_write_cr0(vdev, val);
627627
if (ret)
628628
return ret;
@@ -631,7 +631,7 @@ static int ivpu_mmu_reset(struct ivpu_device *vdev)
631631
if (ret)
632632
return ret;
633633

634-
val |= IVPU_MMU_CR0_SMMUEN;
634+
val = REG_SET_FLD(IVPU_MMU_REG_CR0, SMMUEN, val);
635635
return ivpu_mmu_reg_write_cr0(vdev, val);
636636
}
637637

@@ -870,7 +870,47 @@ static u32 *ivpu_mmu_get_event(struct ivpu_device *vdev)
870870
return evt;
871871
}
872872

873-
static int ivpu_mmu_disable_events(struct ivpu_device *vdev, u32 ssid)
873+
static int ivpu_mmu_evtq_set(struct ivpu_device *vdev, bool enable)
874+
{
875+
u32 val = REGV_RD32(IVPU_MMU_REG_CR0);
876+
877+
if (enable)
878+
val = REG_SET_FLD(IVPU_MMU_REG_CR0, EVTQEN, val);
879+
else
880+
val = REG_CLR_FLD(IVPU_MMU_REG_CR0, EVTQEN, val);
881+
REGV_WR32(IVPU_MMU_REG_CR0, val);
882+
883+
return REGV_POLL_FLD(IVPU_MMU_REG_CR0ACK, VAL, val, IVPU_MMU_REG_TIMEOUT_US);
884+
}
885+
886+
static int ivpu_mmu_evtq_enable(struct ivpu_device *vdev)
887+
{
888+
return ivpu_mmu_evtq_set(vdev, true);
889+
}
890+
891+
static int ivpu_mmu_evtq_disable(struct ivpu_device *vdev)
892+
{
893+
return ivpu_mmu_evtq_set(vdev, false);
894+
}
895+
896+
void ivpu_mmu_discard_events(struct ivpu_device *vdev)
897+
{
898+
/*
899+
* Disable event queue (stop MMU from updating the producer)
900+
* to allow synchronization of consumer and producer indexes
901+
*/
902+
ivpu_mmu_evtq_disable(vdev);
903+
904+
vdev->mmu->evtq.cons = REGV_RD32(IVPU_MMU_REG_EVTQ_PROD_SEC);
905+
REGV_WR32(IVPU_MMU_REG_EVTQ_CONS_SEC, vdev->mmu->evtq.cons);
906+
vdev->mmu->evtq.prod = REGV_RD32(IVPU_MMU_REG_EVTQ_PROD_SEC);
907+
908+
ivpu_mmu_evtq_enable(vdev);
909+
910+
drm_WARN_ON_ONCE(&vdev->drm, vdev->mmu->evtq.cons != vdev->mmu->evtq.prod);
911+
}
912+
913+
int ivpu_mmu_disable_ssid_events(struct ivpu_device *vdev, u32 ssid)
874914
{
875915
struct ivpu_mmu_info *mmu = vdev->mmu;
876916
struct ivpu_mmu_cdtab *cdtab = &mmu->cdtab;
@@ -890,45 +930,34 @@ static int ivpu_mmu_disable_events(struct ivpu_device *vdev, u32 ssid)
890930
clflush_cache_range(entry, IVPU_MMU_CDTAB_ENT_SIZE);
891931

892932
ivpu_mmu_cmdq_write_cfgi_all(vdev);
933+
ivpu_mmu_cmdq_sync(vdev);
893934

894935
return 0;
895936
}
896937

897938
void ivpu_mmu_irq_evtq_handler(struct ivpu_device *vdev)
898939
{
899940
struct ivpu_file_priv *file_priv;
900-
u32 last_ssid = -1;
901941
u32 *event;
902942
u32 ssid;
903943

904944
ivpu_dbg(vdev, IRQ, "MMU event queue\n");
905945

906946
while ((event = ivpu_mmu_get_event(vdev))) {
907-
ssid = FIELD_GET(IVPU_MMU_EVT_SSID_MASK, event[0]);
908-
909-
if (ssid == last_ssid)
910-
continue;
947+
ssid = FIELD_GET(IVPU_MMU_EVT_SSID_MASK, *event);
948+
if (ssid == IVPU_GLOBAL_CONTEXT_MMU_SSID) {
949+
ivpu_mmu_dump_event(vdev, event);
950+
ivpu_pm_trigger_recovery(vdev, "MMU event");
951+
return;
952+
}
911953

912-
xa_lock(&vdev->context_xa);
913954
file_priv = xa_load(&vdev->context_xa, ssid);
914955
if (file_priv) {
915-
if (file_priv->has_mmu_faults) {
916-
event = NULL;
917-
} else {
918-
ivpu_mmu_disable_events(vdev, ssid);
919-
file_priv->has_mmu_faults = true;
956+
if (!READ_ONCE(file_priv->has_mmu_faults)) {
957+
ivpu_mmu_dump_event(vdev, event);
958+
WRITE_ONCE(file_priv->has_mmu_faults, true);
920959
}
921960
}
922-
xa_unlock(&vdev->context_xa);
923-
924-
if (event)
925-
ivpu_mmu_dump_event(vdev, event);
926-
927-
if (ssid == IVPU_GLOBAL_CONTEXT_MMU_SSID) {
928-
ivpu_pm_trigger_recovery(vdev, "MMU event");
929-
return;
930-
}
931-
REGV_WR32(IVPU_MMU_REG_EVTQ_CONS_SEC, vdev->mmu->evtq.cons);
932961
}
933962

934963
queue_work(system_wq, &vdev->context_abort_work);

drivers/accel/ivpu/ivpu_mmu.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,5 +47,7 @@ int ivpu_mmu_invalidate_tlb(struct ivpu_device *vdev, u16 ssid);
4747
void ivpu_mmu_irq_evtq_handler(struct ivpu_device *vdev);
4848
void ivpu_mmu_irq_gerr_handler(struct ivpu_device *vdev);
4949
void ivpu_mmu_evtq_dump(struct ivpu_device *vdev);
50+
void ivpu_mmu_discard_events(struct ivpu_device *vdev);
51+
int ivpu_mmu_disable_ssid_events(struct ivpu_device *vdev, u32 ssid);
5052

5153
#endif /* __IVPU_MMU_H__ */

0 commit comments

Comments
 (0)