|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH] xen/pci: fix phantom error path in assign_device()
Currently if an iommu_call() for a phantom function fails, there is no
indication of the failure. Propagate (but don't return) the error code
from the most recently failed iommu_call() and emit a warning. While
here, add a comment to clarify that the loop keeps iterating even when
failure is encountered.
Fixes: cd7dedad8209 ("passthrough: simplify locking and logging")
Signed-off-by: Stewart Hildebrand <stewart.hildebrand@xxxxxxx>
---
Unlike assign_device(), deassign_device() breaks out of the phantom loop
when a failure is encountered and returns the error code. I'm curious
why assign_device() and deassign_device() behave differently? It looks
like it's been that way since
4e9950dc1bd2 ("IOMMU: add phantom function support"). I was initially
inclined to break out of the loop and return the error code in
assign_device(), but adhering to the principle of Chesterton's fence,
I'd first like to understand why this is not currently being done.
I'm aware that I could have avoided introducing a tmp local variable by
using the conditional operator with omitted middle operand:
rc_nonfatal = iommu_call(...) ?: rc_nonfatal;
However, I explicitly chose not to do this to avoid relying on a GNU
extension in yet another place.
---
xen/drivers/passthrough/pci.c | 21 ++++++++++++++-------
1 file changed, 14 insertions(+), 7 deletions(-)
diff --git a/xen/drivers/passthrough/pci.c b/xen/drivers/passthrough/pci.c
index 28ed8ea8172a..71072efceb7a 100644
--- a/xen/drivers/passthrough/pci.c
+++ b/xen/drivers/passthrough/pci.c
@@ -1407,7 +1407,7 @@ static int assign_device(struct domain *d, u16 seg, u8
bus, u8 devfn, u32 flag)
{
const struct domain_iommu *hd = dom_iommu(d);
struct pci_dev *pdev;
- int rc = 0;
+ int rc = 0, rc_nonfatal = 0;
if ( !is_iommu_enabled(d) )
return 0;
@@ -1443,21 +1443,28 @@ static int assign_device(struct domain *d, u16 seg, u8
bus, u8 devfn, u32 flag)
pci_to_dev(pdev), flag)) )
goto done;
- for ( ; pdev->phantom_stride; rc = 0 )
+ while ( pdev->phantom_stride )
{
+ int tmp;
+
devfn += pdev->phantom_stride;
if ( PCI_SLOT(devfn) != PCI_SLOT(pdev->devfn) )
+ {
+ devfn -= pdev->phantom_stride; /* Adjust for printing */
break;
+ }
- rc = iommu_call(hd->platform_ops, assign_device, d, devfn,
- pci_to_dev(pdev), flag);
+ tmp = iommu_call(hd->platform_ops, assign_device, d, devfn,
+ pci_to_dev(pdev), flag);
+ rc_nonfatal = tmp ? tmp : rc_nonfatal;
+ /* Keep iterating even if the iommu call failed. */
}
done:
- if ( rc )
+ if ( rc || rc_nonfatal )
printk(XENLOG_G_WARNING "%pd: assign (%pp) failed (%d)\n",
- d, &PCI_SBDF(seg, bus, devfn), rc);
+ d, &PCI_SBDF(seg, bus, devfn), rc ? rc : rc_nonfatal);
/* The device is assigned to dom_io so mark it as quarantined */
- else if ( d == dom_io )
+ if ( !rc && d == dom_io )
pdev->quarantine = true;
return rc;
base-commit: 1403131596fa77663708f6baa0fee8bf7b95eb5a
--
2.43.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |