|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v5 7/7] VT-d: Fix vt-d Device-TLB flush timeout issue.
>>> On 05.02.16 at 11:18, <quan.xu@xxxxxxxxx> wrote:
> --- a/xen/drivers/passthrough/vtd/qinval.c
> +++ b/xen/drivers/passthrough/vtd/qinval.c
> @@ -229,6 +229,69 @@ int qinval_device_iotlb(struct iommu *iommu,
> return 0;
> }
>
> +static void dev_invalidate_iotlb_timeout(struct iommu *iommu, u16 did,
> + u16 seg, u8 bus, u8 devfn,
> + unsigned int lock)
> +{
> + struct domain *d = NULL;
> + struct pci_dev *pdev;
> +
> + if ( test_bit(did, iommu->domid_bitmap) )
> + d = rcu_lock_domain_by_id(iommu->domid_map[did]);
> +
> + if ( d == NULL )
> + return;
> +
> + for_each_pdev(d, pdev)
> + {
> + if ( (pdev->seg == seg) &&
> + (pdev->bus == bus) &&
> + (pdev->devfn == devfn) )
> + {
> + ASSERT ( pdev->domain );
Stray blanks inside the parentheses.
> + list_del(&pdev->domain_list);
> + pdev->domain = NULL;
> +
> + if ( !(lock & PCIDEVS_LOCK) )
> + spin_lock(&pcidevs_lock);
This is too late - you may not iterate over pdev-s without holding
that lock, and the list_del() may not be done in that case either.
Plus this should be accompanied be an ASSERT() in the else case.
> + if ( pci_hide_device(bus, devfn) )
But now I'm _really_ puzzled: You acquire the exact lock that
pci_hide_device() acquires. Hence, unless I've overlooked an earlier
change, I can't see this as other than an unconditional dead lock. Did
you test this code path at all?
> + {
> + printk(XENLOG_ERR
> + "IOMMU hide device %04x:%02x:%02x.%02x error.",
> + seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
> + }
I hate to repeat myself: SBDF need to be printed in canonical
ssss:bb:dd.f form, to be grep-able. Also no full stops at the end
of log messages please. And (also mentioned before) if there are
error codes available, log them to aid diagnosis of problems.
Also - unnecessary figure braces.
> @@ -350,9 +413,19 @@ static int flush_iotlb_qi(
> queue_invalidate_iotlb(iommu,
> type >> DMA_TLB_FLUSH_GRANU_OFFSET, dr,
> dw, did, size_order, 0, addr);
> - if ( flush_dev_iotlb )
> - ret = dev_invalidate_iotlb(iommu, did, addr, size_order, type);
> +
> + /*
> + * Before Device-TLB invalidation we need to synchronize
> + * invalidation completions with hardware.
> + */
> rc = invalidate_sync(iommu);
> + if ( rc )
> + return rc;
> +
> + if ( flush_dev_iotlb )
> + ret = dev_invalidate_iotlb(iommu, did, addr, size_order,
> + type, lock);
> +
> if ( !ret )
> ret = rc;
These two lines have now become pointless, and hence should
be deleted.
> @@ -162,6 +162,18 @@ int dev_invalidate_iotlb(struct iommu *iommu, u16 did,
> return -EOPNOTSUPP;
> }
>
> + /*
> + * Synchronize with hardware for Device-TLB invalidate
> + * descriptor.
> + */
> + ret = dev_invalidate_iotlb_sync(iommu, did, pdev->seg,
> + pdev->bus, pdev->devfn, lock);
> + if ( ret )
> + printk(XENLOG_ERR
> + "Flush error %d on device %04x:%02x:%02x.%02x \n",
> + ret, pdev->seg, pdev->bus, PCI_SLOT(pdev->devfn),
> + PCI_FUNC(pdev->devfn));
> +
> if ( !ret )
> ret = rc;
The two context lines here show that you're now clobbering "ret".
Jan
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |