Re: [PATCH] iommu/vt-d: Fix IQE handling to cover all descriptors in submission range
Baolu Lu <[email protected]>
| Newsgroups | dev.linux.lists.iommu,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
On 8/20/26 22:47, Guanghui Feng wrote: > Currently, qi_check_fault() only handles IQE (Invalidation Queue Error) > when the faulting descriptor index exactly matches the first descriptor > of the current submission (head == index). This is too restrictive in > multi-descriptor submissions where the error could occur at any > descriptor within the batch. > > If the IQE is triggered by a descriptor that belongs to the current > submission but is not at the starting index, the function returns 0 > without clearing the IQE fault status. Since hardware stops fetching > new descriptors until IQE is cleared, this leads to an indefinite wait > on the wait descriptor completion - effectively a deadlock. > > Fix this by expanding the IQE handling condition to cover all descriptors > within the circular range [index, wait_index]. Use explicit bounds > checking that properly handles the wrap-around case of the circular > queue. > > Signed-off-by: Guanghui Feng <[email protected]> > Signed-off-by: bikuan.zbk <[email protected]> > --- > drivers/iommu/intel/dmar.c | 15 ++++++++++++++- > 1 file changed, 14 insertions(+), 1 deletion(-) > > diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c > index ba675b08cd20..ecc95af06f61 100644 > --- a/drivers/iommu/intel/dmar.c > +++ b/drivers/iommu/intel/dmar.c > @@ -1366,8 +1366,21 @@ static int qi_check_fault(struct intel_iommu *iommu, int index, int wait_index) > * is cleared. > */ > if (fault & DMA_FSTS_IQE) { > + int head_idx; > + > head = readl(iommu->reg + DMAR_IQH_REG); > - if ((head >> shift) == index) { > + head_idx = head >> shift; > + > + /* > + * The faulting descriptor can be anywhere within the current > + * submission's range [index, wait_index]. Since the queue is > + * circular, this submission may wrap around QI_LENGTH > + * (index > wait_index in that case), so check both the > + * non-wrapped and wrapped cases of the range. > + */ > + if (index <= wait_index ? > + (head_idx >= index && head_idx <= wait_index) : > + (head_idx >= index || head_idx <= wait_index)) { > struct qi_desc *desc = qi->desc + head; > > /* Could you also please take a look at the comments from Sashiko? https://sashiko.dev/#/patchset/20260805042012.2363698-1-guanghuifeng%40linux.alibaba.com https://sashiko.dev/#/patchset/20260820144741.920858-1-guanghuifeng%40linux.alibaba.com No worries about the pre-existing issues. I’ll take care of them. Thanks, baolu