aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/radeon_device.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_device.c')
-rw-r--r--drivers/gpu/drm/radeon/radeon_device.c47
1 files changed, 20 insertions, 27 deletions
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/*