From 0c4cecae5e083db5cfd596354a91a056b5321ae5 Mon Sep 17 00:00:00 2001 From: Tomasz Bursztyka Date: Wed, 24 Feb 2021 09:59:53 +0100 Subject: [PATCH] drivers/interrupt_controller: Add a timeout check on VT-D QI operation QI operation are not supposed to last forever. It's not an actual timeout based on clock, but a dummy counter instead. That's because system clock might not have beed initialized yet, since VT-D's init comes first (and that same init will use QI...) Signed-off-by: Tomasz Bursztyka --- drivers/interrupt_controller/intc_intel_vtd.c | 14 ++++++++++++++ drivers/interrupt_controller/intc_intel_vtd.h | 3 +++ 2 files changed, 17 insertions(+) diff --git a/drivers/interrupt_controller/intc_intel_vtd.c b/drivers/interrupt_controller/intc_intel_vtd.c index 76f478de03e..91a457e8ed7 100644 --- a/drivers/interrupt_controller/intc_intel_vtd.c +++ b/drivers/interrupt_controller/intc_intel_vtd.c @@ -117,6 +117,7 @@ static int vtd_qi_send(const struct device *dev, union qi_wait_descriptor wait_desc = { 0 }; struct qi_descriptor *desc; uint32_t wait_status; + uint32_t wait_count; desc = (struct qi_descriptor *)((uintptr_t)data->qi + data->qi_tail); @@ -141,12 +142,25 @@ static int vtd_qi_send(const struct device *dev, vtd_write_reg64(dev, VTD_IQT_REG, data->qi_tail); + wait_count = 0; + while (wait_status != QI_WAIT_STATUS_COMPLETE) { + /* We cannot use timeout here, this function being called + * at init time, it might result that the system clock + * is not initialized yet since VT-D init comes first. + */ + if (wait_count > QI_WAIT_COUNT_LIMIT) { + printk("QI timeout\n"); + return -ETIME; + } + if (vtd_read_reg32(dev, VTD_FSTS_REG) & VTD_FSTS_IQE) { + printk("QI error\n"); return -EIO; } vtd_pause_cpu(); + wait_count++; } return 0; diff --git a/drivers/interrupt_controller/intc_intel_vtd.h b/drivers/interrupt_controller/intc_intel_vtd.h index 4e4ab45620e..682cd5562e5 100644 --- a/drivers/interrupt_controller/intc_intel_vtd.h +++ b/drivers/interrupt_controller/intc_intel_vtd.h @@ -98,6 +98,9 @@ union qi_wait_descriptor { #define QI_WAIT_STATUS_INCOMPLETE 0x0UL #define QI_WAIT_STATUS_COMPLETE 0x1UL +/* Arbitrary wait counter limit */ +#define QI_WAIT_COUNT_LIMIT 100 + struct vtd_ictl_data { union vtd_irte irte[IRTE_NUM] __aligned(0x1000); struct qi_descriptor qi[QI_NUM] __aligned(0x1000);