Pull the check for VM ownership into ppt_find().
This reduces some code duplication. One behavior change is that ppt_assign_device() will now only succeed if the device is unowned. Previously, a device could be assigned to the same VM multiple times, but each time it was assigned, the device's state was reset. Reviewed by: markj, grehan MFC after: 2 weeks Sponsored by: Chelsio Communications Differential Revision: https://reviews.freebsd.org/D27301
This commit is contained in:
parent
1925586e03
commit
908dca3ef4
@ -199,8 +199,8 @@ static devclass_t ppt_devclass;
|
||||
DEFINE_CLASS_0(ppt, ppt_driver, ppt_methods, sizeof(struct pptdev));
|
||||
DRIVER_MODULE(ppt, pci, ppt_driver, ppt_devclass, NULL, NULL);
|
||||
|
||||
static struct pptdev *
|
||||
ppt_find(int bus, int slot, int func)
|
||||
static int
|
||||
ppt_find(struct vm *vm, int bus, int slot, int func, struct pptdev **pptp)
|
||||
{
|
||||
device_t dev;
|
||||
struct pptdev *ppt;
|
||||
@ -212,9 +212,15 @@ ppt_find(int bus, int slot, int func)
|
||||
s = pci_get_slot(dev);
|
||||
f = pci_get_function(dev);
|
||||
if (bus == b && slot == s && func == f)
|
||||
return (ppt);
|
||||
break;
|
||||
}
|
||||
return (NULL);
|
||||
|
||||
if (ppt == NULL)
|
||||
return (ENOENT);
|
||||
if (ppt->vm != vm) /* Make sure we own this device */
|
||||
return (EBUSY);
|
||||
*pptp = ppt;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -378,50 +384,40 @@ int
|
||||
ppt_assign_device(struct vm *vm, int bus, int slot, int func)
|
||||
{
|
||||
struct pptdev *ppt;
|
||||
int error;
|
||||
|
||||
ppt = ppt_find(bus, slot, func);
|
||||
if (ppt != NULL) {
|
||||
/*
|
||||
* If this device is owned by a different VM then we
|
||||
* cannot change its owner.
|
||||
*/
|
||||
if (ppt->vm != NULL && ppt->vm != vm)
|
||||
return (EBUSY);
|
||||
/* Passing NULL requires the device to be unowned. */
|
||||
error = ppt_find(NULL, bus, slot, func, &ppt);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
pci_save_state(ppt->dev);
|
||||
ppt_pci_reset(ppt->dev);
|
||||
pci_restore_state(ppt->dev);
|
||||
ppt->vm = vm;
|
||||
iommu_add_device(vm_iommu_domain(vm), pci_get_rid(ppt->dev));
|
||||
return (0);
|
||||
}
|
||||
return (ENOENT);
|
||||
pci_save_state(ppt->dev);
|
||||
ppt_pci_reset(ppt->dev);
|
||||
pci_restore_state(ppt->dev);
|
||||
ppt->vm = vm;
|
||||
iommu_add_device(vm_iommu_domain(vm), pci_get_rid(ppt->dev));
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
ppt_unassign_device(struct vm *vm, int bus, int slot, int func)
|
||||
{
|
||||
struct pptdev *ppt;
|
||||
int error;
|
||||
|
||||
ppt = ppt_find(bus, slot, func);
|
||||
if (ppt != NULL) {
|
||||
/*
|
||||
* If this device is not owned by this 'vm' then bail out.
|
||||
*/
|
||||
if (ppt->vm != vm)
|
||||
return (EBUSY);
|
||||
error = ppt_find(vm, bus, slot, func, &ppt);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
pci_save_state(ppt->dev);
|
||||
ppt_pci_reset(ppt->dev);
|
||||
pci_restore_state(ppt->dev);
|
||||
ppt_unmap_mmio(vm, ppt);
|
||||
ppt_teardown_msi(ppt);
|
||||
ppt_teardown_msix(ppt);
|
||||
iommu_remove_device(vm_iommu_domain(vm), pci_get_rid(ppt->dev));
|
||||
ppt->vm = NULL;
|
||||
return (0);
|
||||
}
|
||||
return (ENOENT);
|
||||
pci_save_state(ppt->dev);
|
||||
ppt_pci_reset(ppt->dev);
|
||||
pci_restore_state(ppt->dev);
|
||||
ppt_unmap_mmio(vm, ppt);
|
||||
ppt_teardown_msi(ppt);
|
||||
ppt_teardown_msix(ppt);
|
||||
iommu_remove_device(vm_iommu_domain(vm), pci_get_rid(ppt->dev));
|
||||
ppt->vm = NULL;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
@ -452,25 +448,22 @@ ppt_map_mmio(struct vm *vm, int bus, int slot, int func,
|
||||
struct pptseg *seg;
|
||||
struct pptdev *ppt;
|
||||
|
||||
ppt = ppt_find(bus, slot, func);
|
||||
if (ppt != NULL) {
|
||||
if (ppt->vm != vm)
|
||||
return (EBUSY);
|
||||
error = ppt_find(vm, bus, slot, func, &ppt);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
for (i = 0; i < MAX_MMIOSEGS; i++) {
|
||||
seg = &ppt->mmio[i];
|
||||
if (seg->len == 0) {
|
||||
error = vm_map_mmio(vm, gpa, len, hpa);
|
||||
if (error == 0) {
|
||||
seg->gpa = gpa;
|
||||
seg->len = len;
|
||||
}
|
||||
return (error);
|
||||
for (i = 0; i < MAX_MMIOSEGS; i++) {
|
||||
seg = &ppt->mmio[i];
|
||||
if (seg->len == 0) {
|
||||
error = vm_map_mmio(vm, gpa, len, hpa);
|
||||
if (error == 0) {
|
||||
seg->gpa = gpa;
|
||||
seg->len = len;
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
return (ENOSPC);
|
||||
}
|
||||
return (ENOENT);
|
||||
return (ENOSPC);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -512,11 +505,9 @@ ppt_setup_msi(struct vm *vm, int vcpu, int bus, int slot, int func,
|
||||
if (numvec < 0 || numvec > MAX_MSIMSGS)
|
||||
return (EINVAL);
|
||||
|
||||
ppt = ppt_find(bus, slot, func);
|
||||
if (ppt == NULL)
|
||||
return (ENOENT);
|
||||
if (ppt->vm != vm) /* Make sure we own this device */
|
||||
return (EBUSY);
|
||||
error = ppt_find(vm, bus, slot, func, &ppt);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
/* Reject attempts to enable MSI while MSI-X is active. */
|
||||
if (ppt->msix.num_msgs != 0 && numvec != 0)
|
||||
@ -605,11 +596,9 @@ ppt_setup_msix(struct vm *vm, int vcpu, int bus, int slot, int func,
|
||||
int numvec, alloced, rid, error;
|
||||
size_t res_size, cookie_size, arg_size;
|
||||
|
||||
ppt = ppt_find(bus, slot, func);
|
||||
if (ppt == NULL)
|
||||
return (ENOENT);
|
||||
if (ppt->vm != vm) /* Make sure we own this device */
|
||||
return (EBUSY);
|
||||
error = ppt_find(vm, bus, slot, func, &ppt);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
/* Reject attempts to enable MSI-X while MSI is active. */
|
||||
if (ppt->msi.num_msgs != 0)
|
||||
@ -713,12 +702,11 @@ int
|
||||
ppt_disable_msix(struct vm *vm, int bus, int slot, int func)
|
||||
{
|
||||
struct pptdev *ppt;
|
||||
int error;
|
||||
|
||||
ppt = ppt_find(bus, slot, func);
|
||||
if (ppt == NULL)
|
||||
return (ENOENT);
|
||||
if (ppt->vm != vm) /* Make sure we own this device */
|
||||
return (EBUSY);
|
||||
error = ppt_find(vm, bus, slot, func, &ppt);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
ppt_teardown_msix(ppt);
|
||||
return (0);
|
||||
|
Loading…
Reference in New Issue
Block a user