diff options
author | Alex Deucher <alexander.deucher@amd.com> | 2013-03-04 12:47:46 -0500 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2013-06-27 10:49:07 -0400 |
commit | 75efdee11b5da3acbbeb43a9b93a9c4fe6d5bec8 (patch) | |
tree | dfdb40d6b02d6a613a5d20ae8a343ac0d024dfcc /drivers/gpu/drm/radeon/radeon_device.c | |
parent | f93bdefe6269067afc85688d45c646cde350e0d8 (diff) |
drm/radeon: implement simple doorbell page allocator
The doorbell aperture is a PCI BAR whose pages can be
mapped to compute resources for things like wptrs
for userspace queues.
This patch maps the BAR and sets up a simple allocator
to allocate pages from the BAR.
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_device.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_device.c | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 4e97ff79b7f..82335e38ec4 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -232,6 +232,94 @@ void radeon_scratch_free(struct radeon_device *rdev, uint32_t reg) } /* + * GPU doorbell aperture helpers function. + */ +/** + * radeon_doorbell_init - Init doorbell driver information. + * + * @rdev: radeon_device pointer + * + * Init doorbell driver information (CIK) + * Returns 0 on success, error on failure. + */ +int radeon_doorbell_init(struct radeon_device *rdev) +{ + int i; + + /* doorbell bar mapping */ + rdev->doorbell.base = pci_resource_start(rdev->pdev, 2); + rdev->doorbell.size = pci_resource_len(rdev->pdev, 2); + + /* limit to 4 MB for now */ + if (rdev->doorbell.size > (4 * 1024 * 1024)) + rdev->doorbell.size = 4 * 1024 * 1024; + + rdev->doorbell.ptr = ioremap(rdev->doorbell.base, rdev->doorbell.size); + if (rdev->doorbell.ptr == NULL) { + return -ENOMEM; + } + DRM_INFO("doorbell mmio base: 0x%08X\n", (uint32_t)rdev->doorbell.base); + DRM_INFO("doorbell mmio size: %u\n", (unsigned)rdev->doorbell.size); + + rdev->doorbell.num_pages = rdev->doorbell.size / PAGE_SIZE; + + for (i = 0; i < rdev->doorbell.num_pages; i++) { + rdev->doorbell.free[i] = true; + } + return 0; +} + +/** + * radeon_doorbell_fini - Tear down doorbell driver information. + * + * @rdev: radeon_device pointer + * + * Tear down doorbell driver information (CIK) + */ +void radeon_doorbell_fini(struct radeon_device *rdev) +{ + iounmap(rdev->doorbell.ptr); + rdev->doorbell.ptr = NULL; +} + +/** + * radeon_doorbell_get - Allocate a doorbell page + * + * @rdev: radeon_device pointer + * @doorbell: doorbell page number + * + * Allocate a doorbell page for use by the driver (all asics). + * Returns 0 on success or -EINVAL on failure. + */ +int radeon_doorbell_get(struct radeon_device *rdev, u32 *doorbell) +{ + int i; + + for (i = 0; i < rdev->doorbell.num_pages; i++) { + if (rdev->doorbell.free[i]) { + rdev->doorbell.free[i] = false; + *doorbell = i; + return 0; + } + } + return -EINVAL; +} + +/** + * radeon_doorbell_free - Free a doorbell page + * + * @rdev: radeon_device pointer + * @doorbell: doorbell page number + * + * Free a doorbell page allocated for use by the driver (all asics) + */ +void radeon_doorbell_free(struct radeon_device *rdev, u32 doorbell) +{ + if (doorbell < rdev->doorbell.num_pages) + rdev->doorbell.free[doorbell] = true; +} + +/* * radeon_wb_*() * Writeback is the the method by which the the GPU updates special pages * in memory with the status of certain GPU events (fences, ring pointers, @@ -1162,6 +1250,10 @@ int radeon_device_init(struct radeon_device *rdev, DRM_INFO("register mmio base: 0x%08X\n", (uint32_t)rdev->rmmio_base); DRM_INFO("register mmio size: %u\n", (unsigned)rdev->rmmio_size); + /* doorbell bar mapping */ + if (rdev->family >= CHIP_BONAIRE) + radeon_doorbell_init(rdev); + /* io port mapping */ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { if (pci_resource_flags(rdev->pdev, i) & IORESOURCE_IO) { @@ -1239,6 +1331,8 @@ void radeon_device_fini(struct radeon_device *rdev) rdev->rio_mem = NULL; iounmap(rdev->rmmio); rdev->rmmio = NULL; + if (rdev->family >= CHIP_BONAIRE) + radeon_doorbell_fini(rdev); radeon_debugfs_remove_files(rdev); } |