drivers/gpu/drm/amd/amdxcp/amdgpu_xcp_drv.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/amd/amdxcp/amdgpu_xcp_drv.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/amd/amdxcp/amdgpu_xcp_drv.c
Extension
.c
Size
3842 bytes
Lines
158
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 xcp_device {
	struct drm_device drm;
	struct platform_device *pdev;
};

static const struct drm_driver amdgpu_xcp_driver = {
	.driver_features = DRIVER_GEM | DRIVER_RENDER,
	.name = "amdgpu_xcp_drv",
	.major = 1,
	.minor = 0,
};

static int8_t pdev_num;
static struct xcp_device *xcp_dev[MAX_XCP_PLATFORM_DEVICE];
static DEFINE_MUTEX(xcp_mutex);

int amdgpu_xcp_drm_dev_alloc(struct drm_device **ddev)
{
	struct platform_device *pdev;
	struct xcp_device *pxcp_dev;
	char *dev_name;
	int ret, i;

	guard(mutex)(&xcp_mutex);

	if (pdev_num >= MAX_XCP_PLATFORM_DEVICE)
		return -ENODEV;

	for (i = 0; i < MAX_XCP_PLATFORM_DEVICE; i++) {
		if (!xcp_dev[i])
			break;
	}

	if (i >= MAX_XCP_PLATFORM_DEVICE)
		return -ENODEV;

	dev_name = kasprintf(GFP_KERNEL, "amdgpu_xcp_%d", i);
	if (!dev_name)
		return -ENOMEM;

	pdev = platform_device_register_simple(dev_name, -1, NULL, 0);
	kfree(dev_name);
	if (IS_ERR(pdev))
		return PTR_ERR(pdev);

	if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL)) {
		ret = -ENOMEM;
		goto out_unregister;
	}

	pxcp_dev = devm_drm_dev_alloc(&pdev->dev, &amdgpu_xcp_driver, struct xcp_device, drm);
	if (IS_ERR(pxcp_dev)) {
		ret = PTR_ERR(pxcp_dev);
		goto out_devres;
	}

	xcp_dev[i] = pxcp_dev;
	xcp_dev[i]->pdev = pdev;
	*ddev = &pxcp_dev->drm;
	pdev_num++;

	return 0;

out_devres:
	devres_release_group(&pdev->dev, NULL);
out_unregister:
	platform_device_unregister(pdev);

	return ret;
}
EXPORT_SYMBOL(amdgpu_xcp_drm_dev_alloc);

static void free_xcp_dev(int8_t index)
{
	if ((index < MAX_XCP_PLATFORM_DEVICE) && (xcp_dev[index])) {
		struct platform_device *pdev = xcp_dev[index]->pdev;

		devres_release_group(&pdev->dev, NULL);
		platform_device_unregister(pdev);

		xcp_dev[index] = NULL;
		pdev_num--;
	}
}

void amdgpu_xcp_drm_dev_free(struct drm_device *ddev)
{
	int8_t i;

	guard(mutex)(&xcp_mutex);

Annotation

Implementation Notes