diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_device.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_device.c | 47 |
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 | */ |
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 | /* |