aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian König <christian.koenig@amd.com>2014-05-27 10:49:22 -0400
committerAlex Deucher <alexander.deucher@amd.com>2014-06-02 10:25:13 -0400
commit1aab5514ca9604e0263f658a067da0189c86a35b (patch)
treef96125f31d9cd42d673ee2e6dcffbfcff9f37eed
parent1a0e79184132c5dc0e03a4047eacecc52c24deae (diff)
drm/radeon: rework page flip handling v3
Instead of trying to flip inside the vblank period when the buffer is idle, offload blocking for idle to a kernel thread and program the flip directly into the hardware. v2: add error handling, fix EBUSY handling v3: add proper exclusive_lock handling Signed-off-by: Christian König <christian.koenig@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r--drivers/gpu/drm/radeon/radeon.h16
-rw-r--r--drivers/gpu/drm/radeon/radeon_display.c245
-rw-r--r--drivers/gpu/drm/radeon/radeon_mode.h4
3 files changed, 150 insertions, 115 deletions
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 4ae304d7e932..736bfa2c7528 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -676,14 +676,16 @@ void radeon_doorbell_free(struct radeon_device *rdev, u32 doorbell);
676 * IRQS. 676 * IRQS.
677 */ 677 */
678 678
679struct radeon_unpin_work { 679struct radeon_flip_work {
680 struct work_struct work; 680 struct work_struct flip_work;
681 struct radeon_device *rdev; 681 struct work_struct unpin_work;
682 int crtc_id; 682 struct radeon_device *rdev;
683 struct radeon_fence *fence; 683 int crtc_id;
684 struct drm_framebuffer *fb;
684 struct drm_pending_vblank_event *event; 685 struct drm_pending_vblank_event *event;
685 struct radeon_bo *old_rbo; 686 struct radeon_bo *old_rbo;
686 u64 new_crtc_base; 687 struct radeon_bo *new_rbo;
688 struct radeon_fence *fence;
687}; 689};
688 690
689struct r500_irq_stat_regs { 691struct r500_irq_stat_regs {
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 88e3cbe11dad..6b3de5ca5bc7 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -249,16 +249,21 @@ static void radeon_crtc_destroy(struct drm_crtc *crtc)
249 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); 249 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
250 250
251 drm_crtc_cleanup(crtc); 251 drm_crtc_cleanup(crtc);
252 destroy_workqueue(radeon_crtc->flip_queue);
252 kfree(radeon_crtc); 253 kfree(radeon_crtc);
253} 254}
254 255
255/* 256/**
256 * Handle unpin events outside the interrupt handler proper. 257 * radeon_unpin_work_func - unpin old buffer object
258 *
259 * @__work - kernel work item
260 *
261 * Unpin the old frame buffer object outside of the interrupt handler
257 */ 262 */
258static void radeon_unpin_work_func(struct work_struct *__work) 263static void radeon_unpin_work_func(struct work_struct *__work)
259{ 264{
260 struct radeon_unpin_work *work = 265 struct radeon_flip_work *work =
261 container_of(__work, struct radeon_unpin_work, work); 266 container_of(__work, struct radeon_flip_work, unpin_work);
262 int r; 267 int r;
263 268
264 /* unpin of the old buffer */ 269 /* unpin of the old buffer */
@@ -279,30 +284,19 @@ static void radeon_unpin_work_func(struct work_struct *__work)
279void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id) 284void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id)
280{ 285{
281 struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; 286 struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
282 struct radeon_unpin_work *work; 287 struct radeon_flip_work *work;
283 unsigned long flags; 288 unsigned long flags;
284 u32 update_pending; 289 u32 update_pending;
285 int vpos, hpos; 290 int vpos, hpos;
286 291
287 spin_lock_irqsave(&rdev->ddev->event_lock, flags); 292 spin_lock_irqsave(&rdev->ddev->event_lock, flags);
288 work = radeon_crtc->unpin_work; 293 work = radeon_crtc->flip_work;
289 if (work == NULL || 294 if (work == NULL) {
290 (work->fence && !radeon_fence_signaled(work->fence))) {
291 spin_unlock_irqrestore(&rdev->ddev->event_lock, flags); 295 spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
292 return; 296 return;
293 } 297 }
294 /* New pageflip, or just completion of a previous one? */ 298
295 if (!radeon_crtc->deferred_flip_completion) { 299 update_pending = radeon_page_flip_pending(rdev, crtc_id);
296 /* do the flip (mmio) */
297 radeon_page_flip(rdev, crtc_id, work->new_crtc_base);
298 update_pending = radeon_page_flip_pending(rdev, crtc_id);
299 } else {
300 /* This is just a completion of a flip queued in crtc
301 * at last invocation. Make sure we go directly to
302 * completion routine.
303 */
304 update_pending = 0;
305 }
306 300
307 /* Has the pageflip already completed in crtc, or is it certain 301 /* Has the pageflip already completed in crtc, or is it certain
308 * to complete in this vblank? 302 * to complete in this vblank?
@@ -320,19 +314,9 @@ void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id)
320 */ 314 */
321 update_pending = 0; 315 update_pending = 0;
322 } 316 }
323 if (update_pending) { 317 spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
324 /* crtc didn't flip in this target vblank interval, 318 if (!update_pending)
325 * but flip is pending in crtc. It will complete it
326 * in next vblank interval, so complete the flip at
327 * next vblank irq.
328 */
329 radeon_crtc->deferred_flip_completion = 1;
330 spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
331 return;
332 } else {
333 spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
334 radeon_crtc_handle_flip(rdev, crtc_id); 319 radeon_crtc_handle_flip(rdev, crtc_id);
335 }
336} 320}
337 321
338/** 322/**
@@ -346,7 +330,7 @@ void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id)
346void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id) 330void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id)
347{ 331{
348 struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; 332 struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
349 struct radeon_unpin_work *work; 333 struct radeon_flip_work *work;
350 unsigned long flags; 334 unsigned long flags;
351 335
352 /* this can happen at init */ 336 /* this can happen at init */
@@ -354,15 +338,14 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id)
354 return; 338 return;
355 339
356 spin_lock_irqsave(&rdev->ddev->event_lock, flags); 340 spin_lock_irqsave(&rdev->ddev->event_lock, flags);
357 work = radeon_crtc->unpin_work; 341 work = radeon_crtc->flip_work;
358 if (work == NULL) { 342 if (work == NULL) {
359 spin_unlock_irqrestore(&rdev->ddev->event_lock, flags); 343 spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
360 return; 344 return;
361 } 345 }
362 346
363 /* Pageflip (will be) certainly completed in this vblank. Clean up. */ 347 /* Pageflip completed. Clean up. */
364 radeon_crtc->unpin_work = NULL; 348 radeon_crtc->flip_work = NULL;
365 radeon_crtc->deferred_flip_completion = 0;
366 349
367 /* wakeup userspace */ 350 /* wakeup userspace */
368 if (work->event) 351 if (work->event)
@@ -372,83 +355,69 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id)
372 355
373 radeon_fence_unref(&work->fence); 356 radeon_fence_unref(&work->fence);
374 radeon_irq_kms_pflip_irq_get(rdev, work->crtc_id); 357 radeon_irq_kms_pflip_irq_get(rdev, work->crtc_id);
375 schedule_work(&work->work); 358 queue_work(radeon_crtc->flip_queue, &work->unpin_work);
376} 359}
377 360
378static int radeon_crtc_page_flip(struct drm_crtc *crtc, 361/**
379 struct drm_framebuffer *fb, 362 * radeon_flip_work_func - page flip framebuffer
380 struct drm_pending_vblank_event *event, 363 *
381 uint32_t page_flip_flags) 364 * @work - kernel work item
365 *
366 * Wait for the buffer object to become idle and do the actual page flip
367 */
368static void radeon_flip_work_func(struct work_struct *__work)
382{ 369{
383 struct drm_device *dev = crtc->dev; 370 struct radeon_flip_work *work =
384 struct radeon_device *rdev = dev->dev_private; 371 container_of(__work, struct radeon_flip_work, flip_work);
385 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); 372 struct radeon_device *rdev = work->rdev;
386 struct radeon_framebuffer *old_radeon_fb; 373 struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[work->crtc_id];
387 struct radeon_framebuffer *new_radeon_fb;
388 struct drm_gem_object *obj;
389 struct radeon_bo *rbo;
390 struct radeon_unpin_work *work;
391 unsigned long flags;
392 u32 tiling_flags, pitch_pixels;
393 u64 base;
394 int r;
395 374
396 work = kzalloc(sizeof *work, GFP_KERNEL); 375 struct drm_crtc *crtc = &radeon_crtc->base;
397 if (work == NULL) 376 struct drm_framebuffer *fb = work->fb;
398 return -ENOMEM;
399 377
400 work->event = event; 378 uint32_t tiling_flags, pitch_pixels;
401 work->rdev = rdev; 379 uint64_t base;
402 work->crtc_id = radeon_crtc->crtc_id;
403 old_radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
404 new_radeon_fb = to_radeon_framebuffer(fb);
405 /* schedule unpin of the old buffer */
406 obj = old_radeon_fb->obj;
407 /* take a reference to the old object */
408 drm_gem_object_reference(obj);
409 rbo = gem_to_radeon_bo(obj);
410 work->old_rbo = rbo;
411 obj = new_radeon_fb->obj;
412 rbo = gem_to_radeon_bo(obj);
413 380
414 spin_lock(&rbo->tbo.bdev->fence_lock); 381 unsigned long flags;
415 if (rbo->tbo.sync_obj) 382 int r;
416 work->fence = radeon_fence_ref(rbo->tbo.sync_obj);
417 spin_unlock(&rbo->tbo.bdev->fence_lock);
418 383
419 INIT_WORK(&work->work, radeon_unpin_work_func); 384 down_read(&rdev->exclusive_lock);
385 while (work->fence) {
386 r = radeon_fence_wait(work->fence, false);
387 if (r == -EDEADLK) {
388 up_read(&rdev->exclusive_lock);
389 r = radeon_gpu_reset(rdev);
390 down_read(&rdev->exclusive_lock);
391 }
420 392
421 /* We borrow the event spin lock for protecting unpin_work */ 393 if (r) {
422 spin_lock_irqsave(&dev->event_lock, flags); 394 DRM_ERROR("failed to wait on page flip fence (%d)!\n",
423 if (radeon_crtc->unpin_work) { 395 r);
424 DRM_DEBUG_DRIVER("flip queue: crtc already busy\n"); 396 goto cleanup;
425 r = -EBUSY; 397 } else
426 goto unlock_free; 398 radeon_fence_unref(&work->fence);
427 } 399 }
428 radeon_crtc->unpin_work = work;
429 radeon_crtc->deferred_flip_completion = 0;
430 spin_unlock_irqrestore(&dev->event_lock, flags);
431 400
432 /* pin the new buffer */ 401 /* pin the new buffer */
433 DRM_DEBUG_DRIVER("flip-ioctl() cur_fbo = %p, cur_bbo = %p\n", 402 DRM_DEBUG_DRIVER("flip-ioctl() cur_fbo = %p, cur_bbo = %p\n",
434 work->old_rbo, rbo); 403 work->old_rbo, work->new_rbo);
435 404
436 r = radeon_bo_reserve(rbo, false); 405 r = radeon_bo_reserve(work->new_rbo, false);
437 if (unlikely(r != 0)) { 406 if (unlikely(r != 0)) {
438 DRM_ERROR("failed to reserve new rbo buffer before flip\n"); 407 DRM_ERROR("failed to reserve new rbo buffer before flip\n");
439 goto pflip_cleanup; 408 goto cleanup;
440 } 409 }
441 /* Only 27 bit offset for legacy CRTC */ 410 /* Only 27 bit offset for legacy CRTC */
442 r = radeon_bo_pin_restricted(rbo, RADEON_GEM_DOMAIN_VRAM, 411 r = radeon_bo_pin_restricted(work->new_rbo, RADEON_GEM_DOMAIN_VRAM,
443 ASIC_IS_AVIVO(rdev) ? 0 : 1 << 27, &base); 412 ASIC_IS_AVIVO(rdev) ? 0 : 1 << 27, &base);
444 if (unlikely(r != 0)) { 413 if (unlikely(r != 0)) {
445 radeon_bo_unreserve(rbo); 414 radeon_bo_unreserve(work->new_rbo);
446 r = -EINVAL; 415 r = -EINVAL;
447 DRM_ERROR("failed to pin new rbo buffer before flip\n"); 416 DRM_ERROR("failed to pin new rbo buffer before flip\n");
448 goto pflip_cleanup; 417 goto cleanup;
449 } 418 }
450 radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL); 419 radeon_bo_get_tiling_flags(work->new_rbo, &tiling_flags, NULL);
451 radeon_bo_unreserve(rbo); 420 radeon_bo_unreserve(work->new_rbo);
452 421
453 if (!ASIC_IS_AVIVO(rdev)) { 422 if (!ASIC_IS_AVIVO(rdev)) {
454 /* crtc offset is from display base addr not FB location */ 423 /* crtc offset is from display base addr not FB location */
@@ -486,28 +455,91 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
486 base &= ~7; 455 base &= ~7;
487 } 456 }
488 457
489 spin_lock_irqsave(&dev->event_lock, flags); 458 /* We borrow the event spin lock for protecting flip_work */
490 work->new_crtc_base = base; 459 spin_lock_irqsave(&crtc->dev->event_lock, flags);
491 spin_unlock_irqrestore(&dev->event_lock, flags);
492
493 /* update crtc fb */
494 crtc->primary->fb = fb;
495 460
496 /* set the proper interrupt */ 461 /* set the proper interrupt */
497 radeon_irq_kms_pflip_irq_get(rdev, radeon_crtc->crtc_id); 462 radeon_irq_kms_pflip_irq_get(rdev, radeon_crtc->crtc_id);
498 463
499 return 0; 464 /* do the flip (mmio) */
465 radeon_page_flip(rdev, radeon_crtc->crtc_id, base);
500 466
501pflip_cleanup: 467 spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
502 spin_lock_irqsave(&dev->event_lock, flags); 468 up_read(&rdev->exclusive_lock);
503 radeon_crtc->unpin_work = NULL; 469
504unlock_free: 470 return;
505 spin_unlock_irqrestore(&dev->event_lock, flags); 471
506 drm_gem_object_unreference_unlocked(old_radeon_fb->obj); 472cleanup:
473 drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base);
507 radeon_fence_unref(&work->fence); 474 radeon_fence_unref(&work->fence);
508 kfree(work); 475 kfree(work);
476 up_read(&rdev->exclusive_lock);
477}
478
479static int radeon_crtc_page_flip(struct drm_crtc *crtc,
480 struct drm_framebuffer *fb,
481 struct drm_pending_vblank_event *event,
482 uint32_t page_flip_flags)
483{
484 struct drm_device *dev = crtc->dev;
485 struct radeon_device *rdev = dev->dev_private;
486 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
487 struct radeon_framebuffer *old_radeon_fb;
488 struct radeon_framebuffer *new_radeon_fb;
489 struct drm_gem_object *obj;
490 struct radeon_flip_work *work;
491 unsigned long flags;
492
493 work = kzalloc(sizeof *work, GFP_KERNEL);
494 if (work == NULL)
495 return -ENOMEM;
496
497 INIT_WORK(&work->flip_work, radeon_flip_work_func);
498 INIT_WORK(&work->unpin_work, radeon_unpin_work_func);
509 499
510 return r; 500 work->rdev = rdev;
501 work->crtc_id = radeon_crtc->crtc_id;
502 work->fb = fb;
503 work->event = event;
504
505 /* schedule unpin of the old buffer */
506 old_radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
507 obj = old_radeon_fb->obj;
508
509 /* take a reference to the old object */
510 drm_gem_object_reference(obj);
511 work->old_rbo = gem_to_radeon_bo(obj);
512
513 new_radeon_fb = to_radeon_framebuffer(fb);
514 obj = new_radeon_fb->obj;
515 work->new_rbo = gem_to_radeon_bo(obj);
516
517 spin_lock(&work->new_rbo->tbo.bdev->fence_lock);
518 if (work->new_rbo->tbo.sync_obj)
519 work->fence = radeon_fence_ref(work->new_rbo->tbo.sync_obj);
520 spin_unlock(&work->new_rbo->tbo.bdev->fence_lock);
521
522 /* update crtc fb */
523 crtc->primary->fb = fb;
524
525 /* We borrow the event spin lock for protecting flip_work */
526 spin_lock_irqsave(&crtc->dev->event_lock, flags);
527
528 if (radeon_crtc->flip_work) {
529 DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
530 spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
531 drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base);
532 radeon_fence_unref(&work->fence);
533 kfree(work);
534 return -EBUSY;
535 }
536 radeon_crtc->flip_work = work;
537
538 spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
539
540 queue_work(radeon_crtc->flip_queue, &work->flip_work);
541
542 return 0;
511} 543}
512 544
513static int 545static int
@@ -577,6 +609,7 @@ static void radeon_crtc_init(struct drm_device *dev, int index)
577 609
578 drm_mode_crtc_set_gamma_size(&radeon_crtc->base, 256); 610 drm_mode_crtc_set_gamma_size(&radeon_crtc->base, 256);
579 radeon_crtc->crtc_id = index; 611 radeon_crtc->crtc_id = index;
612 radeon_crtc->flip_queue = create_singlethread_workqueue("radeon-crtc");
580 rdev->mode_info.crtcs[index] = radeon_crtc; 613 rdev->mode_info.crtcs[index] = radeon_crtc;
581 614
582 if (rdev->family >= CHIP_BONAIRE) { 615 if (rdev->family >= CHIP_BONAIRE) {
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 718be1a932ac..ea72ad889a11 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -325,8 +325,8 @@ struct radeon_crtc {
325 struct drm_display_mode native_mode; 325 struct drm_display_mode native_mode;
326 int pll_id; 326 int pll_id;
327 /* page flipping */ 327 /* page flipping */
328 struct radeon_unpin_work *unpin_work; 328 struct workqueue_struct *flip_queue;
329 int deferred_flip_completion; 329 struct radeon_flip_work *flip_work;
330 /* pll sharing */ 330 /* pll sharing */
331 struct radeon_atom_ss ss; 331 struct radeon_atom_ss ss;
332 bool ss_enabled; 332 bool ss_enabled;