drivers/vfio/platform/vfio_platform_irq.c

Source file repositories/reference/linux-study-clean/drivers/vfio/platform/vfio_platform_irq.c

File Facts

System
Linux kernel
Corpus path
drivers/vfio/platform/vfio_platform_irq.c
Extension
.c
Size
8379 bytes
Lines
369
Domain
Driver Families
Bucket
drivers/vfio
Inferred role
Driver Families: implementation source
Status
source 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

if (hwirq < 0) {
			ret = -EINVAL;
			goto err;
		}

		spin_lock_init(&vdev->irqs[i].lock);

		vdev->irqs[i].flags = VFIO_IRQ_INFO_EVENTFD;

		if (irq_get_trigger_type(hwirq) & IRQ_TYPE_LEVEL_MASK) {
			vdev->irqs[i].flags |= VFIO_IRQ_INFO_MASKABLE
						| VFIO_IRQ_INFO_AUTOMASKED;
			handler = vfio_automasked_irq_handler;
		}

		vdev->irqs[i].count = 1;
		vdev->irqs[i].hwirq = hwirq;
		vdev->irqs[i].masked = false;
		vdev->irqs[i].name = kasprintf(GFP_KERNEL_ACCOUNT,
					       "vfio-irq[%d](%s)", hwirq,
					       vdev->name);
		if (!vdev->irqs[i].name) {
			ret = -ENOMEM;
			goto err;
		}

		ret = request_irq(hwirq, handler, IRQF_NO_AUTOEN,
				  vdev->irqs[i].name, &vdev->irqs[i]);
		if (ret) {
			kfree(vdev->irqs[i].name);
			vdev->irqs[i].name = ERR_PTR(ret);
		}
	}

	vdev->num_irqs = cnt;

	return 0;
err:
	for (--i; i >= 0; i--) {
		if (!IS_ERR(vdev->irqs[i].name)) {
			free_irq(vdev->irqs[i].hwirq, &vdev->irqs[i]);
			kfree(vdev->irqs[i].name);
		}
	}
	kfree(vdev->irqs);
	return ret;
}

void vfio_platform_irq_cleanup(struct vfio_platform_device *vdev)
{
	int i;

	for (i = 0; i < vdev->num_irqs; i++) {
		vfio_virqfd_disable(&vdev->irqs[i].mask);
		vfio_virqfd_disable(&vdev->irqs[i].unmask);
		if (!IS_ERR(vdev->irqs[i].name)) {
			free_irq(vdev->irqs[i].hwirq, &vdev->irqs[i]);
			if (vdev->irqs[i].trigger)
				eventfd_ctx_put(vdev->irqs[i].trigger);
			kfree(vdev->irqs[i].name);
		}
	}

	vdev->num_irqs = 0;
	kfree(vdev->irqs);
}

Annotation

Implementation Notes