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:
parent
82961458de
commit
0c4cecae5e
2 changed files with 17 additions and 0 deletions
|
@ -117,6 +117,7 @@ static int vtd_qi_send(const struct device *dev,
|
||||||
union qi_wait_descriptor wait_desc = { 0 };
|
union qi_wait_descriptor wait_desc = { 0 };
|
||||||
struct qi_descriptor *desc;
|
struct qi_descriptor *desc;
|
||||||
uint32_t wait_status;
|
uint32_t wait_status;
|
||||||
|
uint32_t wait_count;
|
||||||
|
|
||||||
desc = (struct qi_descriptor *)((uintptr_t)data->qi + data->qi_tail);
|
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);
|
vtd_write_reg64(dev, VTD_IQT_REG, data->qi_tail);
|
||||||
|
|
||||||
|
wait_count = 0;
|
||||||
|
|
||||||
while (wait_status != QI_WAIT_STATUS_COMPLETE) {
|
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) {
|
if (vtd_read_reg32(dev, VTD_FSTS_REG) & VTD_FSTS_IQE) {
|
||||||
|
printk("QI error\n");
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
vtd_pause_cpu();
|
vtd_pause_cpu();
|
||||||
|
wait_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -98,6 +98,9 @@ union qi_wait_descriptor {
|
||||||
#define QI_WAIT_STATUS_INCOMPLETE 0x0UL
|
#define QI_WAIT_STATUS_INCOMPLETE 0x0UL
|
||||||
#define QI_WAIT_STATUS_COMPLETE 0x1UL
|
#define QI_WAIT_STATUS_COMPLETE 0x1UL
|
||||||
|
|
||||||
|
/* Arbitrary wait counter limit */
|
||||||
|
#define QI_WAIT_COUNT_LIMIT 100
|
||||||
|
|
||||||
struct vtd_ictl_data {
|
struct vtd_ictl_data {
|
||||||
union vtd_irte irte[IRTE_NUM] __aligned(0x1000);
|
union vtd_irte irte[IRTE_NUM] __aligned(0x1000);
|
||||||
struct qi_descriptor qi[QI_NUM] __aligned(0x1000);
|
struct qi_descriptor qi[QI_NUM] __aligned(0x1000);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue