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 <tomasz.bursztyka@linux.intel.com>
This commit is contained in:
Tomasz Bursztyka 2021-02-24 09:59:53 +01:00 committed by Anas Nashif
commit 0c4cecae5e
2 changed files with 17 additions and 0 deletions

View file

@ -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;

View file

@ -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);