drivers/gpu/drm/amd/amdkfd/kfd_chardev.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
Extension
.c
Size
97600 bytes
Lines
3778
Domain
Driver Families
Bucket
drivers/gpu
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

static const struct file_operations kfd_fops = {
	.owner = THIS_MODULE,
	.unlocked_ioctl = kfd_ioctl,
	.compat_ioctl = compat_ptr_ioctl,
	.open = kfd_open,
	.release = kfd_release,
	.mmap = kfd_mmap,
};

static int kfd_char_dev_major = -1;
struct device *kfd_device;
static const struct class kfd_class = {
	.name = kfd_dev_name,
};

/*
 * Cache the address space of the chardev on first open so that the reset
 * path can drop all userspace mappings of doorbell and MMIO ranges via
 * unmap_mapping_range().
 */
static struct address_space *kfd_dev_mapping;

void kfd_dev_unmap_mapping_range(loff_t const holebegin, loff_t const holelen)
{
	struct address_space *mapping = READ_ONCE(kfd_dev_mapping);

	if (mapping)
		unmap_mapping_range(mapping, holebegin, holelen, 1);
}

static inline struct kfd_process_device *kfd_lock_pdd_by_id(struct kfd_process *p, __u32 gpu_id)
{
	struct kfd_process_device *pdd;

	mutex_lock(&p->mutex);
	pdd = kfd_process_device_data_by_id(p, gpu_id);

	if (pdd)
		return pdd;

	mutex_unlock(&p->mutex);
	return NULL;
}

static inline void kfd_unlock_pdd(struct kfd_process_device *pdd)
{
	mutex_unlock(&pdd->process->mutex);
}

int kfd_chardev_init(void)
{
	int err = 0;

	kfd_char_dev_major = register_chrdev(0, kfd_dev_name, &kfd_fops);
	err = kfd_char_dev_major;
	if (err < 0)
		goto err_register_chrdev;

	err = class_register(&kfd_class);
	if (err)
		goto err_class_create;

	kfd_device = device_create(&kfd_class, NULL,
				   MKDEV(kfd_char_dev_major, 0),
				   NULL, kfd_dev_name);
	err = PTR_ERR(kfd_device);
	if (IS_ERR(kfd_device))
		goto err_device_create;

	return 0;

err_device_create:
	class_unregister(&kfd_class);
err_class_create:
	unregister_chrdev(kfd_char_dev_major, kfd_dev_name);
err_register_chrdev:
	return err;
}

void kfd_chardev_exit(void)
{
	device_destroy(&kfd_class, MKDEV(kfd_char_dev_major, 0));
	class_unregister(&kfd_class);
	unregister_chrdev(kfd_char_dev_major, kfd_dev_name);
	kfd_device = NULL;
}


static int kfd_open(struct inode *inode, struct file *filep)
{

Annotation

Implementation Notes