|
@@ -231,6 +231,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
|
|
@@ -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);
|
|
|
}
|
|
|
|