On Wed, Jun 26, 2013 at 09:22:11AM -0400, alexdeucher@gmail.com wrote:
From: Alex Deucher alexander.deucher@amd.com
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.
This doorbell stuff is cryptic, is that some memory on the GPU ? Or is it more like a register file ? ie what is backing the pci bar.
Also probably want to use bitmap as i dont think gcc will turn bool array into a bitmap.
Cheers, Jerome
Signed-off-by: Alex Deucher alexander.deucher@amd.com
drivers/gpu/drm/radeon/cik.c | 38 +++++++++++++ drivers/gpu/drm/radeon/radeon.h | 21 +++++++ drivers/gpu/drm/radeon/radeon_device.c | 94 ++++++++++++++++++++++++++++++++ 3 files changed, 153 insertions(+), 0 deletions(-)
diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index bb7dbc4..5c28fa5 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -121,6 +121,44 @@ u32 cik_get_xclk(struct radeon_device *rdev) return reference_clock; }
+/**
- cik_mm_rdoorbell - read a doorbell dword
- @rdev: radeon_device pointer
- @offset: byte offset into the aperture
- Returns the value in the doorbell aperture at the
- requested offset (CIK).
- */
+u32 cik_mm_rdoorbell(struct radeon_device *rdev, u32 offset) +{
- if (offset < rdev->doorbell.size) {
return readl(((void __iomem *)rdev->doorbell.ptr) + offset);
- } else {
DRM_ERROR("reading beyond doorbell aperture: 0x%08x!\n", offset);
return 0;
- }
+}
+/**
- cik_mm_wdoorbell - write a doorbell dword
- @rdev: radeon_device pointer
- @offset: byte offset into the aperture
- @v: value to write
- Writes @v to the doorbell aperture at the
- requested offset (CIK).
- */
+void cik_mm_wdoorbell(struct radeon_device *rdev, u32 offset, u32 v) +{
- if (offset < rdev->doorbell.size) {
writel(v, ((void __iomem *)rdev->doorbell.ptr) + offset);
- } else {
DRM_ERROR("writing beyond doorbell aperture: 0x%08x!\n", offset);
- }
+}
#define BONAIRE_IO_MC_REGS_SIZE 36
static const u32 bonaire_io_mc_regs[BONAIRE_IO_MC_REGS_SIZE][2] = diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index ad4e68a..a2a3430 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -556,6 +556,20 @@ struct radeon_scratch { int radeon_scratch_get(struct radeon_device *rdev, uint32_t *reg); void radeon_scratch_free(struct radeon_device *rdev, uint32_t reg);
+/*
- GPU doorbell structures, functions & helpers
- */
+struct radeon_doorbell {
- u32 num_pages;
- bool free[1024];
- /* doorbell mmio */
- resource_size_t base;
- resource_size_t size;
- void __iomem *ptr;
+};
+int radeon_doorbell_get(struct radeon_device *rdev, u32 *page); +void radeon_doorbell_free(struct radeon_device *rdev, u32 doorbell);
/*
- IRQS.
@@ -1711,6 +1725,7 @@ struct radeon_device { struct radeon_gart gart; struct radeon_mode_info mode_info; struct radeon_scratch scratch;
- struct radeon_doorbell doorbell; struct radeon_mman mman; struct radeon_fence_driver fence_drv[RADEON_NUM_RINGS]; wait_queue_head_t fence_queue;
@@ -1784,6 +1799,9 @@ void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v, u32 r100_io_rreg(struct radeon_device *rdev, u32 reg); void r100_io_wreg(struct radeon_device *rdev, u32 reg, u32 v);
+u32 cik_mm_rdoorbell(struct radeon_device *rdev, u32 offset); +void cik_mm_wdoorbell(struct radeon_device *rdev, u32 offset, u32 v);
/*
- Cast helper
*/ @@ -1833,6 +1851,9 @@ void r100_io_wreg(struct radeon_device *rdev, u32 reg, u32 v); #define RREG32_IO(reg) r100_io_rreg(rdev, (reg)) #define WREG32_IO(reg, v) r100_io_wreg(rdev, (reg), (v))
+#define RDOORBELL32(offset) cik_mm_rdoorbell(rdev, (offset)) +#define WDOORBELL32(offset, v) cik_mm_wdoorbell(rdev, (offset), (v))
/*
- Indirect registers accessor
*/ diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 4e97ff7..82335e3 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_debugfs_remove_files(rdev);radeon_doorbell_fini(rdev);
}
-- 1.7.7.5
dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel