in vfio.c [889:965]
void vfio_unregister_group_dev(struct vfio_device *device)
{
struct vfio_group *group = device->group;
struct vfio_unbound_dev *unbound;
unsigned int i = 0;
bool interrupted = false;
long rc;
/*
* When the device is removed from the group, the group suddenly
* becomes non-viable; the device has a driver (until the unbind
* completes), but it's not present in the group. This is bad news
* for any external users that need to re-acquire a group reference
* in order to match and release their existing reference. To
* solve this, we track such devices on the unbound_list to bridge
* the gap until they're fully unbound.
*/
unbound = kzalloc(sizeof(*unbound), GFP_KERNEL);
if (unbound) {
unbound->dev = device->dev;
mutex_lock(&group->unbound_lock);
list_add(&unbound->unbound_next, &group->unbound_list);
mutex_unlock(&group->unbound_lock);
}
WARN_ON(!unbound);
vfio_device_put(device);
rc = try_wait_for_completion(&device->comp);
while (rc <= 0) {
if (device->ops->request)
device->ops->request(device, i++);
if (interrupted) {
rc = wait_for_completion_timeout(&device->comp,
HZ * 10);
} else {
rc = wait_for_completion_interruptible_timeout(
&device->comp, HZ * 10);
if (rc < 0) {
interrupted = true;
dev_warn(device->dev,
"Device is currently in use, task"
" \"%s\" (%d) "
"blocked until device is released",
current->comm, task_pid_nr(current));
}
}
}
mutex_lock(&group->device_lock);
list_del(&device->group_next);
group->dev_counter--;
mutex_unlock(&group->device_lock);
/*
* In order to support multiple devices per group, devices can be
* plucked from the group while other devices in the group are still
* in use. The container persists with this group and those remaining
* devices still attached. If the user creates an isolation violation
* by binding this device to another driver while the group is still in
* use, that's their fault. However, in the case of removing the last,
* or potentially the only, device in the group there can be no other
* in-use devices in the group. The user has done their due diligence
* and we should lay no claims to those devices. In order to do that,
* we need to make sure the group is detached from the container.
* Without this stall, we're potentially racing with a user process
* that may attempt to immediately bind this device to another driver.
*/
if (list_empty(&group->device_list))
wait_event(group->container_q, !group->container);
if (group->type == VFIO_NO_IOMMU || group->type == VFIO_EMULATED_IOMMU)
iommu_group_remove_device(device->dev);
/* Matches the get in vfio_register_group_dev() */
vfio_group_put(group);
}