break;
ret = hd->platform_ops->reassign_device(d, target, devfn,
pci_to_dev(pdev));
- if ( !ret )
- continue;
-
- printk(XENLOG_G_ERR "%pd: deassign %04x:%02x:%02x.%u failed (%d)\n",
- d, seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn), ret);
- return ret;
+ if ( ret )
+ goto out;
}
devfn = pdev->devfn;
ret = hd->platform_ops->reassign_device(d, target, devfn,
pci_to_dev(pdev));
if ( ret )
- {
- dprintk(XENLOG_G_ERR,
- "%pd: deassign device (%04x:%02x:%02x.%u) failed\n",
- d, seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
- return ret;
- }
+ goto out;
if ( pdev->domain == hardware_domain )
pdev->quarantine = false;
pdev->fault.count = 0;
+ out:
+ if ( ret )
+ printk(XENLOG_G_ERR "%pd: deassign (%04x:%02x:%02x.%u) failed (%d)\n",
+ d, seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn), ret);
+
return ret;
}
{
bus = pdev->bus;
devfn = pdev->devfn;
- if ( deassign_device(d, pdev->seg, bus, devfn) )
- printk("domain %d: deassign device (%04x:%02x:%02x.%u) failed!\n",
- d->domain_id, pdev->seg, bus,
- PCI_SLOT(devfn), PCI_FUNC(devfn));
+ deassign_device(d, pdev->seg, bus, devfn);
}
pcidevs_unlock();
struct pci_dev *pdev;
int rc = 0;
- pcidevs_lock();
-
+ ASSERT(pcidevs_locked());
pdev = pci_get_pdev(seg, bus, devfn);
if ( !pdev )
pdev->domain != dom_io )
rc = -EBUSY;
- pcidevs_unlock();
-
return rc;
}
+/* Caller should hold the pcidevs_lock */
static int assign_device(struct domain *d, u16 seg, u8 bus, u8 devfn, u32 flag)
{
const struct domain_iommu *hd = dom_iommu(d);
p2m_get_hostp2m(d)->global_logdirty) )
return -EXDEV;
- if ( !pcidevs_trylock() )
- return -ERESTART;
-
+ /* device_assigned() should already have cleared the device for assignment */
+ ASSERT(pcidevs_locked());
pdev = pci_get_pdev(seg, bus, devfn);
-
- rc = -ENODEV;
- if ( !pdev )
- goto done;
-
- rc = 0;
- if ( d == pdev->domain )
- goto done;
-
- rc = -EBUSY;
- if ( pdev->domain != hardware_domain &&
- pdev->domain != dom_io )
- goto done;
+ ASSERT(pdev && (pdev->domain == hardware_domain ||
+ pdev->domain == dom_io));
if ( pdev->msix )
{
if ( PCI_SLOT(devfn) != PCI_SLOT(pdev->devfn) )
break;
rc = hd->platform_ops->assign_device(d, devfn, pci_to_dev(pdev), flag);
- if ( rc )
- printk(XENLOG_G_WARNING "d%d: assign %04x:%02x:%02x.%u failed (%d)\n",
- d->domain_id, seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
- rc);
}
done:
+ if ( rc )
+ printk(XENLOG_G_WARNING "%pd: assign (%04x:%02x:%02x.%u) failed (%d)\n",
+ d, seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn), rc);
/* The device is assigned to dom_io so mark it as quarantined */
- if ( !rc && d == dom_io )
+ else if ( d == dom_io )
pdev->quarantine = true;
- pcidevs_unlock();
-
return rc;
}
bus = PCI_BUS(machine_sbdf);
devfn = PCI_DEVFN2(machine_sbdf);
+ pcidevs_lock();
ret = device_assigned(seg, bus, devfn);
if ( domctl->cmd == XEN_DOMCTL_test_assign_device )
{
}
break;
}
- if ( !ret )
+ else if ( !ret )
ret = assign_device(d, seg, bus, devfn, flags);
+ pcidevs_unlock();
if ( ret == -ERESTART )
ret = hypercall_create_continuation(__HYPERVISOR_domctl,
"h", u_domctl);
- else if ( ret )
- printk(XENLOG_G_ERR
- "assign %04x:%02x:%02x.%u to dom%d failed (%d)\n",
- seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
- d->domain_id, ret);
-
break;
case XEN_DOMCTL_deassign_device:
pcidevs_lock();
ret = deassign_device(d, seg, bus, devfn);
pcidevs_unlock();
- if ( ret )
- printk(XENLOG_G_ERR
- "deassign %04x:%02x:%02x.%u from dom%d failed (%d)\n",
- seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
- d->domain_id, ret);
-
break;
default: