pdev->fault.count = 0;
- if ( (rc = hd->platform_ops->assign_device(d, devfn, pci_to_dev(pdev), flag)) )
- goto done;
+ rc = hd->platform_ops->assign_device(d, devfn, pci_to_dev(pdev), flag);
- for ( ; pdev->phantom_stride; rc = 0 )
+ while ( pdev->phantom_stride && !rc )
{
devfn += pdev->phantom_stride;
if ( PCI_SLOT(devfn) != PCI_SLOT(pdev->devfn) )
done:
if ( rc )
- printk(XENLOG_G_WARNING "%pd: assign (%pp) failed (%d)\n",
- d, &PCI_SBDF3(seg, bus, devfn), rc);
+ {
+ printk(XENLOG_G_WARNING "%pd: assign %s(%pp) failed (%d)\n",
+ d, devfn != pdev->devfn ? "phantom function " : "",
+ &PCI_SBDF3(seg, bus, devfn), rc);
+
+ if ( devfn != pdev->devfn &&
+ deassign_device(d, seg, bus, pdev->devfn) &&
+ !is_hardware_domain(d) && d != dom_io )
+ /*
+ * Device with phantom functions that failed to both assign and
+ * rollback. Crash the target domain, as the state of the
+ * functions at this point is unknown and Xen has no way to assert
+ * consistent context assignment among them.
+ */
+ domain_crash(d);
+ }
/* The device is assigned to dom_io so mark it as quarantined */
else if ( d == dom_io )
pdev->quarantine = true;