diff options
-rw-r--r-- | drivers/gpu/drm/radeon/cik.c | 36 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon.h | 23 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_device.c | 47 |
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 | */ |
1568 | u32 cik_mm_rdoorbell(struct radeon_device *rdev, u32 offset) | 1568 | u32 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 | */ |
1588 | void cik_mm_wdoorbell(struct radeon_device *rdev, u32 offset, u32 v) | 1588 | void 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 | |||
652 | struct radeon_doorbell { | 654 | struct 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 | ||
661 | int radeon_doorbell_get(struct radeon_device *rdev, u32 *page); | 663 | int 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, | |||
2241 | u32 r100_io_rreg(struct radeon_device *rdev, u32 reg); | 2242 | u32 r100_io_rreg(struct radeon_device *rdev, u32 reg); |
2242 | void r100_io_wreg(struct radeon_device *rdev, u32 reg, u32 v); | 2243 | void r100_io_wreg(struct radeon_device *rdev, u32 reg, u32 v); |
2243 | 2244 | ||
2244 | u32 cik_mm_rdoorbell(struct radeon_device *rdev, u32 offset); | 2245 | u32 cik_mm_rdoorbell(struct radeon_device *rdev, u32 index); |
2245 | void cik_mm_wdoorbell(struct radeon_device *rdev, u32 offset, u32 v); | 2246 | void 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 | */ |
252 | int radeon_doorbell_init(struct radeon_device *rdev) | 252 | int 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 | */ |
301 | int radeon_doorbell_get(struct radeon_device *rdev, u32 *doorbell) | 296 | int 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 | */ |
323 | void radeon_doorbell_free(struct radeon_device *rdev, u32 doorbell) | 316 | void 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 | /* |