void vfio_unregister_group_dev()

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);
}