Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d5754ab8 authored by Andrew Lewycky's avatar Andrew Lewycky Committed by Alex Deucher
Browse files

drm/radeon: use a single doorbell for cik kms compute



A single doorbell page is plenty for cik kms compute.
Use a single page and manage doorbell allocation by
individual doorbells rather than pages.  Identify
doorbells by their index rather than byte offset.

Signed-off-by: default avatarAndrew Lewycky <Andrew.Lewycky@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 4cc948b9
Loading
Loading
Loading
Loading
+16 −20
Original line number Diff line number Diff line
@@ -1560,17 +1560,17 @@ u32 cik_get_xclk(struct radeon_device *rdev)
 * cik_mm_rdoorbell - read a doorbell dword
 *
 * @rdev: radeon_device pointer
 * @offset: byte offset into the aperture
 * @index: doorbell index
 *
 * Returns the value in the doorbell aperture at the
 * requested offset (CIK).
 * requested doorbell index (CIK).
 */
u32 cik_mm_rdoorbell(struct radeon_device *rdev, u32 offset)
u32 cik_mm_rdoorbell(struct radeon_device *rdev, u32 index)
{
	if (offset < rdev->doorbell.size) {
		return readl(((void __iomem *)rdev->doorbell.ptr) + offset);
	if (index < rdev->doorbell.num_doorbells) {
		return readl(rdev->doorbell.ptr + index);
	} else {
		DRM_ERROR("reading beyond doorbell aperture: 0x%08x!\n", offset);
		DRM_ERROR("reading beyond doorbell aperture: 0x%08x!\n", index);
		return 0;
	}
}
@@ -1579,18 +1579,18 @@ u32 cik_mm_rdoorbell(struct radeon_device *rdev, u32 offset)
 * cik_mm_wdoorbell - write a doorbell dword
 *
 * @rdev: radeon_device pointer
 * @offset: byte offset into the aperture
 * @index: doorbell index
 * @v: value to write
 *
 * Writes @v to the doorbell aperture at the
 * requested offset (CIK).
 * requested doorbell index (CIK).
 */
void cik_mm_wdoorbell(struct radeon_device *rdev, u32 offset, u32 v)
void cik_mm_wdoorbell(struct radeon_device *rdev, u32 index, u32 v)
{
	if (offset < rdev->doorbell.size) {
		writel(v, ((void __iomem *)rdev->doorbell.ptr) + offset);
	if (index < rdev->doorbell.num_doorbells) {
		writel(v, rdev->doorbell.ptr + index);
	} else {
		DRM_ERROR("writing beyond doorbell aperture: 0x%08x!\n", offset);
		DRM_ERROR("writing beyond doorbell aperture: 0x%08x!\n", index);
	}
}

@@ -4054,7 +4054,7 @@ void cik_compute_ring_set_wptr(struct radeon_device *rdev,
			       struct radeon_ring *ring)
{
	rdev->wb.wb[ring->wptr_offs/4] = cpu_to_le32(ring->wptr);
	WDOORBELL32(ring->doorbell_offset, ring->wptr);
	WDOORBELL32(ring->doorbell_index, ring->wptr);
}

/**
@@ -4395,10 +4395,6 @@ static int cik_cp_compute_resume(struct radeon_device *rdev)
			return r;
		}

		/* doorbell offset */
		rdev->ring[idx].doorbell_offset =
			(rdev->ring[idx].doorbell_page_num * PAGE_SIZE) + 0;

		/* init the mqd struct */
		memset(buf, 0, sizeof(struct bonaire_mqd));

@@ -4510,7 +4506,7 @@ static int cik_cp_compute_resume(struct radeon_device *rdev)
				RREG32(CP_HQD_PQ_DOORBELL_CONTROL);
			mqd->queue_state.cp_hqd_pq_doorbell_control &= ~DOORBELL_OFFSET_MASK;
			mqd->queue_state.cp_hqd_pq_doorbell_control |=
				DOORBELL_OFFSET(rdev->ring[idx].doorbell_offset / 4);
				DOORBELL_OFFSET(rdev->ring[idx].doorbell_index);
			mqd->queue_state.cp_hqd_pq_doorbell_control |= DOORBELL_EN;
			mqd->queue_state.cp_hqd_pq_doorbell_control &=
				~(DOORBELL_SOURCE | DOORBELL_HIT);
@@ -7841,14 +7837,14 @@ int cik_init(struct radeon_device *rdev)
	ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX];
	ring->ring_obj = NULL;
	r600_ring_init(rdev, ring, 1024 * 1024);
	r = radeon_doorbell_get(rdev, &ring->doorbell_page_num);
	r = radeon_doorbell_get(rdev, &ring->doorbell_index);
	if (r)
		return r;

	ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX];
	ring->ring_obj = NULL;
	r600_ring_init(rdev, ring, 1024 * 1024);
	r = radeon_doorbell_get(rdev, &ring->doorbell_page_num);
	r = radeon_doorbell_get(rdev, &ring->doorbell_index);
	if (r)
		return r;

+12 −11
Original line number Diff line number Diff line
@@ -649,13 +649,15 @@ void radeon_scratch_free(struct radeon_device *rdev, uint32_t reg);
/*
 * GPU doorbell structures, functions & helpers
 */
#define RADEON_MAX_DOORBELLS 1024	/* Reserve at most 1024 doorbell slots for radeon-owned rings. */

struct radeon_doorbell {
	u32			num_pages;
	bool			free[1024];
	/* doorbell mmio */
	resource_size_t		base;
	resource_size_t		size;
	void __iomem			*ptr;
	u32 __iomem		*ptr;
	u32			num_doorbells;	/* Number of doorbells actually reserved for radeon. */
	unsigned long		used[DIV_ROUND_UP(RADEON_MAX_DOORBELLS, BITS_PER_LONG)];
};

int radeon_doorbell_get(struct radeon_device *rdev, u32 *page);
@@ -802,8 +804,7 @@ struct radeon_ring {
	u32 pipe;
	u32 queue;
	struct radeon_bo	*mqd_obj;
	u32 doorbell_page_num;
	u32 doorbell_offset;
	u32 doorbell_index;
	unsigned		wptr_offs;
};

@@ -2241,8 +2242,8 @@ 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);
u32 cik_mm_rdoorbell(struct radeon_device *rdev, u32 index);
void cik_mm_wdoorbell(struct radeon_device *rdev, u32 index, u32 v);

/*
 * Cast helper
@@ -2305,8 +2306,8 @@ void cik_mm_wdoorbell(struct radeon_device *rdev, u32 offset, 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))
#define RDOORBELL32(index) cik_mm_rdoorbell(rdev, (index))
#define WDOORBELL32(index, v) cik_mm_wdoorbell(rdev, (index), (v))

/*
 * Indirect registers accessor
+20 −27
Original line number Diff line number Diff line
@@ -251,28 +251,23 @@ void radeon_scratch_free(struct radeon_device *rdev, uint32_t reg)
 */
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.num_doorbells = min_t(u32, rdev->doorbell.size / sizeof(u32), RADEON_MAX_DOORBELLS);
	if (rdev->doorbell.num_doorbells == 0)
		return -EINVAL;

	rdev->doorbell.ptr = ioremap(rdev->doorbell.base, rdev->doorbell.size);
	rdev->doorbell.ptr = ioremap(rdev->doorbell.base, rdev->doorbell.num_doorbells * sizeof(u32));
	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;
	memset(&rdev->doorbell.used, 0, sizeof(rdev->doorbell.used));

	for (i = 0; i < rdev->doorbell.num_pages; i++) {
		rdev->doorbell.free[i] = true;
	}
	return 0;
}

@@ -290,40 +285,38 @@ void radeon_doorbell_fini(struct radeon_device *rdev)
}

/**
 * radeon_doorbell_get - Allocate a doorbell page
 * radeon_doorbell_get - Allocate a doorbell entry
 *
 * @rdev: radeon_device pointer
 * @doorbell: doorbell page number
 * @doorbell: doorbell index
 *
 * Allocate a doorbell page for use by the driver (all asics).
 * Allocate a doorbell 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;
	unsigned long offset = find_first_zero_bit(rdev->doorbell.used, rdev->doorbell.num_doorbells);
	if (offset < rdev->doorbell.num_doorbells) {
		__set_bit(offset, rdev->doorbell.used);
		*doorbell = offset;
		return 0;
		}
	}
	} else {
		return -EINVAL;
	}
}

/**
 * radeon_doorbell_free - Free a doorbell page
 * radeon_doorbell_free - Free a doorbell entry
 *
 * @rdev: radeon_device pointer
 * @doorbell: doorbell page number
 * @doorbell: doorbell index
 *
 * Free a doorbell page allocated for use by the driver (all asics)
 * Free a doorbell 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;
	if (doorbell < rdev->doorbell.num_doorbells)
		__clear_bit(doorbell, rdev->doorbell.used);
}

/*