drivers/vfio/pci/vfio_pci_core.c

Source file repositories/reference/linux-study-clean/drivers/vfio/pci/vfio_pci_core.c

File Facts

System
Linux kernel
Corpus path
drivers/vfio/pci/vfio_pci_core.c
Extension
.c
Size
72341 bytes
Lines
2643
Domain
Driver Families
Bucket
drivers/vfio
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct pci_driver *drv = pci_dev_driver(pdev);

		if (drv && drv != pci_dev_driver(vdev->pdev))
			pci_warn(vdev->pdev,
				 "VF %s bound to driver %s while PF bound to driver %s\n",
				 pci_name(pdev), drv->name,
				 pci_dev_driver(vdev->pdev)->name);
	}

	return 0;
}

static int vfio_pci_vf_init(struct vfio_pci_core_device *vdev)
{
	struct pci_dev *pdev = vdev->pdev;
	struct vfio_pci_core_device *cur;
	struct pci_dev *physfn;
	int ret;

	if (pdev->is_virtfn) {
		/*
		 * If this VF was created by our vfio_pci_core_sriov_configure()
		 * then we can find the PF vfio_pci_core_device now, and due to
		 * the locking in pci_disable_sriov() it cannot change until
		 * this VF device driver is removed.
		 */
		physfn = pci_physfn(vdev->pdev);
		mutex_lock(&vfio_pci_sriov_pfs_mutex);
		list_for_each_entry(cur, &vfio_pci_sriov_pfs, sriov_pfs_item) {
			if (cur->pdev == physfn) {
				vdev->sriov_pf_core_dev = cur;
				break;
			}
		}
		mutex_unlock(&vfio_pci_sriov_pfs_mutex);
		return 0;
	}

	/* Not a SRIOV PF */
	if (!pdev->is_physfn)
		return 0;

	vdev->vf_token = kzalloc_obj(*vdev->vf_token);
	if (!vdev->vf_token)
		return -ENOMEM;

	mutex_init(&vdev->vf_token->lock);
	uuid_gen(&vdev->vf_token->uuid);

	vdev->nb.notifier_call = vfio_pci_bus_notifier;
	ret = bus_register_notifier(&pci_bus_type, &vdev->nb);
	if (ret) {
		kfree(vdev->vf_token);
		return ret;
	}
	return 0;
}

static void vfio_pci_vf_uninit(struct vfio_pci_core_device *vdev)
{
	if (!vdev->vf_token)
		return;

	bus_unregister_notifier(&pci_bus_type, &vdev->nb);
	WARN_ON(vdev->vf_token->users);
	mutex_destroy(&vdev->vf_token->lock);
	kfree(vdev->vf_token);
}

static int vfio_pci_vga_init(struct vfio_pci_core_device *vdev)
{
	struct pci_dev *pdev = vdev->pdev;
	int ret;

	if (!vfio_pci_is_vga(pdev))
		return 0;

	ret = aperture_remove_conflicting_pci_devices(pdev, vdev->vdev.ops->name);
	if (ret)
		return ret;

	ret = vga_client_register(pdev, vfio_pci_set_decode);
	if (ret)
		return ret;
	vga_set_legacy_decoding(pdev, vfio_pci_set_decode(pdev, false));
	return 0;
}

static void vfio_pci_vga_uninit(struct vfio_pci_core_device *vdev)
{

Annotation

Implementation Notes