aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorAndrew Lewycky <Andrew.Lewycky@amd.com>2013-11-13 15:54:17 -0500
committerAlex Deucher <alexander.deucher@amd.com>2013-11-15 15:56:22 -0500
commitd5754ab8f9b0f36ab3d6825a3555db48f28145d4 (patch)
tree0c942f43eacfaee5c1b56ea0c5330cfa790f738a /drivers/gpu/drm
parent4cc948b94a222c310ae089c36718aac7a03aec90 (diff)
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: Andrew Lewycky <Andrew.Lewycky@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/radeon/cik.c36
-rw-r--r--drivers/gpu/drm/radeon/radeon.h23
-rw-r--r--drivers/gpu/drm/radeon/radeon_device.c47
3 files changed, 48 insertions, 58 deletions
diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
index c1698978a8f1..08aa58ef8d0a 100644
--- a/drivers/gpu/drm/radeon/cik.c
+++ b/drivers/gpu/drm/radeon/cik.c
@@ -1560,17 +1560,17 @@ u32 cik_get_xclk(struct radeon_device *rdev)
1560 * cik_mm_rdoorbell - read a doorbell dword 1560 * cik_mm_rdoorbell - read a doorbell dword
1561 * 1561 *
1562 * @rdev: radeon_device pointer 1562 * @rdev: radeon_device pointer
1563 * @offset: byte offset into the aperture 1563 * @index: doorbell index
1564 * 1564 *
1565 * Returns the value in the doorbell aperture at the 1565 * Returns the value in the doorbell aperture at the
1566 * requested offset (CIK). 1566 * requested doorbell index (CIK).
1567 */ 1567 */
1568u32 cik_mm_rdoorbell(struct radeon_device *rdev, u32 offset) 1568u32 cik_mm_rdoorbell(struct radeon_device *rdev, u32 index)
1569{ 1569{
1570 if (offset < rdev->doorbell.size) { 1570 if (index < rdev->doorbell.num_doorbells) {
1571 return readl(((void __iomem *)rdev->doorbell.ptr) + offset); 1571 return readl(rdev->doorbell.ptr + index);
1572 } else { 1572 } else {
1573 DRM_ERROR("reading beyond doorbell aperture: 0x%08x!\n", offset); 1573 DRM_ERROR("reading beyond doorbell aperture: 0x%08x!\n", index);
1574 return 0; 1574 return 0;
1575 } 1575 }
1576} 1576}
@@ -1579,18 +1579,18 @@ u32 cik_mm_rdoorbell(struct radeon_device *rdev, u32 offset)
1579 * cik_mm_wdoorbell - write a doorbell dword 1579 * cik_mm_wdoorbell - write a doorbell dword
1580 * 1580 *
1581 * @rdev: radeon_device pointer 1581 * @rdev: radeon_device pointer
1582 * @offset: byte offset into the aperture 1582 * @index: doorbell index
1583 * @v: value to write 1583 * @v: value to write
1584 * 1584 *
1585 * Writes @v to the doorbell aperture at the 1585 * Writes @v to the doorbell aperture at the
1586 * requested offset (CIK). 1586 * requested doorbell index (CIK).
1587 */ 1587 */
1588void cik_mm_wdoorbell(struct radeon_device *rdev, u32 offset, u32 v) 1588void cik_mm_wdoorbell(struct radeon_device *rdev, u32 index, u32 v)
1589{ 1589{
1590 if (offset < rdev->doorbell.size) { 1590 if (index < rdev->doorbell.num_doorbells) {
1591 writel(v, ((void __iomem *)rdev->doorbell.ptr) + offset); 1591 writel(v, rdev->doorbell.ptr + index);
1592 } else { 1592 } else {
1593 DRM_ERROR("writing beyond doorbell aperture: 0x%08x!\n", offset); 1593 DRM_ERROR("writing beyond doorbell aperture: 0x%08x!\n", index);
1594 } 1594 }
1595} 1595}
1596 1596
@@ -4054,7 +4054,7 @@ void cik_compute_ring_set_wptr(struct radeon_device *rdev,
4054 struct radeon_ring *ring) 4054 struct radeon_ring *ring)
4055{ 4055{
4056 rdev->wb.wb[ring->wptr_offs/4] = cpu_to_le32(ring->wptr); 4056 rdev->wb.wb[ring->wptr_offs/4] = cpu_to_le32(ring->wptr);
4057 WDOORBELL32(ring->doorbell_offset, ring->wptr); 4057 WDOORBELL32(ring->doorbell_index, ring->wptr);
4058} 4058}
4059 4059
4060/** 4060/**
@@ -4395,10 +4395,6 @@ static int cik_cp_compute_resume(struct radeon_device *rdev)
4395 return r; 4395 return r;
4396 } 4396 }
4397 4397
4398 /* doorbell offset */
4399 rdev->ring[idx].doorbell_offset =
4400 (rdev->ring[idx].doorbell_page_num * PAGE_SIZE) + 0;
4401
4402 /* init the mqd struct */ 4398 /* init the mqd struct */
4403 memset(buf, 0, sizeof(struct bonaire_mqd)); 4399 memset(buf, 0, sizeof(struct bonaire_mqd));
4404 4400
@@ -4510,7 +4506,7 @@ static int cik_cp_compute_resume(struct radeon_device *rdev)
4510 RREG32(CP_HQD_PQ_DOORBELL_CONTROL); 4506 RREG32(CP_HQD_PQ_DOORBELL_CONTROL);
4511 mqd->queue_state.cp_hqd_pq_doorbell_control &= ~DOORBELL_OFFSET_MASK; 4507 mqd->queue_state.cp_hqd_pq_doorbell_control &= ~DOORBELL_OFFSET_MASK;
4512 mqd->queue_state.cp_hqd_pq_doorbell_control |= 4508 mqd->queue_state.cp_hqd_pq_doorbell_control |=
4513 DOORBELL_OFFSET(rdev->ring[idx].doorbell_offset / 4); 4509 DOORBELL_OFFSET(rdev->ring[idx].doorbell_index);
4514 mqd->queue_state.cp_hqd_pq_doorbell_control |= DOORBELL_EN; 4510 mqd->queue_state.cp_hqd_pq_doorbell_control |= DOORBELL_EN;
4515 mqd->queue_state.cp_hqd_pq_doorbell_control &= 4511 mqd->queue_state.cp_hqd_pq_doorbell_control &=
4516 ~(DOORBELL_SOURCE | DOORBELL_HIT); 4512 ~(DOORBELL_SOURCE | DOORBELL_HIT);
@@ -7841,14 +7837,14 @@ int cik_init(struct radeon_device *rdev)
7841 ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]; 7837 ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX];
7842 ring->ring_obj = NULL; 7838 ring->ring_obj = NULL;
7843 r600_ring_init(rdev, ring, 1024 * 1024); 7839 r600_ring_init(rdev, ring, 1024 * 1024);
7844 r = radeon_doorbell_get(rdev, &ring->doorbell_page_num); 7840 r = radeon_doorbell_get(rdev, &ring->doorbell_index);
7845 if (r) 7841 if (r)
7846 return r; 7842 return r;
7847 7843
7848 ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]; 7844 ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX];
7849 ring->ring_obj = NULL; 7845 ring->ring_obj = NULL;
7850 r600_ring_init(rdev, ring, 1024 * 1024); 7846 r600_ring_init(rdev, ring, 1024 * 1024);
7851 r = radeon_doorbell_get(rdev, &ring->doorbell_page_num); 7847 r = radeon_doorbell_get(rdev, &ring->doorbell_index);
7852 if (r) 7848 if (r)
7853 return r; 7849 return r;
7854 7850
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 2fe2f6332d44..4970ac0ebc80 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -649,13 +649,15 @@ void radeon_scratch_free(struct radeon_device *rdev, uint32_t reg);
649/* 649/*
650 * GPU doorbell structures, functions & helpers 650 * GPU doorbell structures, functions & helpers
651 */ 651 */
652#define RADEON_MAX_DOORBELLS 1024 /* Reserve at most 1024 doorbell slots for radeon-owned rings. */
653
652struct radeon_doorbell { 654struct radeon_doorbell {
653 u32 num_pages;
654 bool free[1024];
655 /* doorbell mmio */ 655 /* doorbell mmio */
656 resource_size_t base; 656 resource_size_t base;
657 resource_size_t size; 657 resource_size_t size;
658 void __iomem *ptr; 658 u32 __iomem *ptr;
659 u32 num_doorbells; /* Number of doorbells actually reserved for radeon. */
660 unsigned long used[DIV_ROUND_UP(RADEON_MAX_DOORBELLS, BITS_PER_LONG)];
659}; 661};
660 662
661int radeon_doorbell_get(struct radeon_device *rdev, u32 *page); 663int radeon_doorbell_get(struct radeon_device *rdev, u32 *page);
@@ -802,8 +804,7 @@ struct radeon_ring {
802 u32 pipe; 804 u32 pipe;
803 u32 queue; 805 u32 queue;
804 struct radeon_bo *mqd_obj; 806 struct radeon_bo *mqd_obj;
805 u32 doorbell_page_num; 807 u32 doorbell_index;
806 u32 doorbell_offset;
807 unsigned wptr_offs; 808 unsigned wptr_offs;
808}; 809};
809 810
@@ -2241,8 +2242,8 @@ void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v,
2241u32 r100_io_rreg(struct radeon_device *rdev, u32 reg); 2242u32 r100_io_rreg(struct radeon_device *rdev, u32 reg);
2242void r100_io_wreg(struct radeon_device *rdev, u32 reg, u32 v); 2243void r100_io_wreg(struct radeon_device *rdev, u32 reg, u32 v);
2243 2244
2244u32 cik_mm_rdoorbell(struct radeon_device *rdev, u32 offset); 2245u32 cik_mm_rdoorbell(struct radeon_device *rdev, u32 index);
2245void cik_mm_wdoorbell(struct radeon_device *rdev, u32 offset, u32 v); 2246void cik_mm_wdoorbell(struct radeon_device *rdev, u32 index, u32 v);
2246 2247
2247/* 2248/*
2248 * Cast helper 2249 * Cast helper
@@ -2305,8 +2306,8 @@ void cik_mm_wdoorbell(struct radeon_device *rdev, u32 offset, u32 v);
2305#define RREG32_IO(reg) r100_io_rreg(rdev, (reg)) 2306#define RREG32_IO(reg) r100_io_rreg(rdev, (reg))
2306#define WREG32_IO(reg, v) r100_io_wreg(rdev, (reg), (v)) 2307#define WREG32_IO(reg, v) r100_io_wreg(rdev, (reg), (v))
2307 2308
2308#define RDOORBELL32(offset) cik_mm_rdoorbell(rdev, (offset)) 2309#define RDOORBELL32(index) cik_mm_rdoorbell(rdev, (index))
2309#define WDOORBELL32(offset, v) cik_mm_wdoorbell(rdev, (offset), (v)) 2310#define WDOORBELL32(index, v) cik_mm_wdoorbell(rdev, (index), (v))
2310 2311
2311/* 2312/*
2312 * Indirect registers accessor 2313 * Indirect registers accessor
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index b9234c43f43d..39b033b441d2 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -251,28 +251,23 @@ void radeon_scratch_free(struct radeon_device *rdev, uint32_t reg)
251 */ 251 */
252int radeon_doorbell_init(struct radeon_device *rdev) 252int radeon_doorbell_init(struct radeon_device *rdev)
253{ 253{
254 int i;
255
256 /* doorbell bar mapping */ 254 /* doorbell bar mapping */
257 rdev->doorbell.base = pci_resource_start(rdev->pdev, 2); 255 rdev->doorbell.base = pci_resource_start(rdev->pdev, 2);
258 rdev->doorbell.size = pci_resource_len(rdev->pdev, 2); 256 rdev->doorbell.size = pci_resource_len(rdev->pdev, 2);
259 257
260 /* limit to 4 MB for now */ 258 rdev->doorbell.num_doorbells = min_t(u32, rdev->doorbell.size / sizeof(u32), RADEON_MAX_DOORBELLS);
261 if (rdev->doorbell.size > (4 * 1024 * 1024)) 259 if (rdev->doorbell.num_doorbells == 0)
262 rdev->doorbell.size = 4 * 1024 * 1024; 260 return -EINVAL;
263 261
264 rdev->doorbell.ptr = ioremap(rdev->doorbell.base, rdev->doorbell.size); 262 rdev->doorbell.ptr = ioremap(rdev->doorbell.base, rdev->doorbell.num_doorbells * sizeof(u32));
265 if (rdev->doorbell.ptr == NULL) { 263 if (rdev->doorbell.ptr == NULL) {
266 return -ENOMEM; 264 return -ENOMEM;
267 } 265 }
268 DRM_INFO("doorbell mmio base: 0x%08X\n", (uint32_t)rdev->doorbell.base); 266 DRM_INFO("doorbell mmio base: 0x%08X\n", (uint32_t)rdev->doorbell.base);
269 DRM_INFO("doorbell mmio size: %u\n", (unsigned)rdev->doorbell.size); 267 DRM_INFO("doorbell mmio size: %u\n", (unsigned)rdev->doorbell.size);
270 268
271 rdev->doorbell.num_pages = rdev->doorbell.size / PAGE_SIZE; 269 memset(&rdev->doorbell.used, 0, sizeof(rdev->doorbell.used));
272 270
273 for (i = 0; i < rdev->doorbell.num_pages; i++) {
274 rdev->doorbell.free[i] = true;
275 }
276 return 0; 271 return 0;
277} 272}
278 273
@@ -290,40 +285,38 @@ void radeon_doorbell_fini(struct radeon_device *rdev)
290} 285}
291 286
292/** 287/**
293 * radeon_doorbell_get - Allocate a doorbell page 288 * radeon_doorbell_get - Allocate a doorbell entry
294 * 289 *
295 * @rdev: radeon_device pointer 290 * @rdev: radeon_device pointer
296 * @doorbell: doorbell page number 291 * @doorbell: doorbell index
297 * 292 *
298 * Allocate a doorbell page for use by the driver (all asics). 293 * Allocate a doorbell for use by the driver (all asics).
299 * Returns 0 on success or -EINVAL on failure. 294 * Returns 0 on success or -EINVAL on failure.
300 */ 295 */
301int radeon_doorbell_get(struct radeon_device *rdev, u32 *doorbell) 296int radeon_doorbell_get(struct radeon_device *rdev, u32 *doorbell)
302{ 297{
303 int i; 298 unsigned long offset = find_first_zero_bit(rdev->doorbell.used, rdev->doorbell.num_doorbells);
304 299 if (offset < rdev->doorbell.num_doorbells) {
305 for (i = 0; i < rdev->doorbell.num_pages; i++) { 300 __set_bit(offset, rdev->doorbell.used);
306 if (rdev->doorbell.free[i]) { 301 *doorbell = offset;
307 rdev->doorbell.free[i] = false; 302 return 0;
308 *doorbell = i; 303 } else {
309 return 0; 304 return -EINVAL;
310 }
311 } 305 }
312 return -EINVAL;
313} 306}
314 307
315/** 308/**
316 * radeon_doorbell_free - Free a doorbell page 309 * radeon_doorbell_free - Free a doorbell entry
317 * 310 *
318 * @rdev: radeon_device pointer 311 * @rdev: radeon_device pointer
319 * @doorbell: doorbell page number 312 * @doorbell: doorbell index
320 * 313 *
321 * Free a doorbell page allocated for use by the driver (all asics) 314 * Free a doorbell allocated for use by the driver (all asics)
322 */ 315 */
323void radeon_doorbell_free(struct radeon_device *rdev, u32 doorbell) 316void radeon_doorbell_free(struct radeon_device *rdev, u32 doorbell)
324{ 317{
325 if (doorbell < rdev->doorbell.num_pages) 318 if (doorbell < rdev->doorbell.num_doorbells)
326 rdev->doorbell.free[doorbell] = true; 319 __clear_bit(doorbell, rdev->doorbell.used);
327} 320}
328 321
329/* 322/*