Commit 901593f2bf221659a605bdc1dcb11376ea934163
Committed by
Daniel Vetter
1 parent
3490ea5de6
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
drm: Only evict the blocks required to create the requested hole
Avoid clobbering adjacent blocks if they happen to expire earlier and amalgamate together to form the requested hole. In passing this fixes a regression from commit ea7b1dd44867e9cd6bac67e7c9fc3f128b5b255c Author: Daniel Vetter <daniel.vetter@ffwll.ch> Date: Fri Feb 18 17:59:12 2011 +0100 drm: mm: track free areas implicitly which swaps the end address for size (with a potential overflow) and effectively causes the eviction code to clobber almost all earlier buffers above the evictee. v2: Check the original hole not the adjusted as the coloring may confuse us when later searching for the overlapping nodes. Also make sure that we do apply the range restriction and color adjustment in the same order for both scanning, searching and insertion. v3: Send the version that was actually tested. Note that this seems to be ducttape of decent quality ot paper over some of our unbind related gpu hangs reported since 3.7. It is not fully effective though, and certainly doesn't fix the underlying bug. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> [danvet: Added note plus bugzilla link and tested-by.] Cc: stable@vger.kernel.org Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=55984 Tested-by: Norbert Preining <preining@logic.at> Acked-by: Dave Airlie <airlied@gmail.com Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Showing 2 changed files with 18 additions and 29 deletions Side-by-side Diff
drivers/gpu/drm/drm_mm.c
... | ... | @@ -221,12 +221,14 @@ |
221 | 221 | |
222 | 222 | BUG_ON(!hole_node->hole_follows || node->allocated); |
223 | 223 | |
224 | - if (mm->color_adjust) | |
225 | - mm->color_adjust(hole_node, color, &adj_start, &adj_end); | |
226 | - | |
227 | 224 | if (adj_start < start) |
228 | 225 | adj_start = start; |
226 | + if (adj_end > end) | |
227 | + adj_end = end; | |
229 | 228 | |
229 | + if (mm->color_adjust) | |
230 | + mm->color_adjust(hole_node, color, &adj_start, &adj_end); | |
231 | + | |
230 | 232 | if (alignment) { |
231 | 233 | unsigned tmp = adj_start % alignment; |
232 | 234 | if (tmp) |
... | ... | @@ -506,7 +508,7 @@ |
506 | 508 | mm->scan_size = size; |
507 | 509 | mm->scanned_blocks = 0; |
508 | 510 | mm->scan_hit_start = 0; |
509 | - mm->scan_hit_size = 0; | |
511 | + mm->scan_hit_end = 0; | |
510 | 512 | mm->scan_check_range = 0; |
511 | 513 | mm->prev_scanned_node = NULL; |
512 | 514 | } |
... | ... | @@ -533,7 +535,7 @@ |
533 | 535 | mm->scan_size = size; |
534 | 536 | mm->scanned_blocks = 0; |
535 | 537 | mm->scan_hit_start = 0; |
536 | - mm->scan_hit_size = 0; | |
538 | + mm->scan_hit_end = 0; | |
537 | 539 | mm->scan_start = start; |
538 | 540 | mm->scan_end = end; |
539 | 541 | mm->scan_check_range = 1; |
... | ... | @@ -552,8 +554,7 @@ |
552 | 554 | struct drm_mm *mm = node->mm; |
553 | 555 | struct drm_mm_node *prev_node; |
554 | 556 | unsigned long hole_start, hole_end; |
555 | - unsigned long adj_start; | |
556 | - unsigned long adj_end; | |
557 | + unsigned long adj_start, adj_end; | |
557 | 558 | |
558 | 559 | mm->scanned_blocks++; |
559 | 560 | |
560 | 561 | |
... | ... | @@ -570,15 +571,9 @@ |
570 | 571 | node->node_list.next = &mm->prev_scanned_node->node_list; |
571 | 572 | mm->prev_scanned_node = node; |
572 | 573 | |
573 | - hole_start = drm_mm_hole_node_start(prev_node); | |
574 | - hole_end = drm_mm_hole_node_end(prev_node); | |
574 | + adj_start = hole_start = drm_mm_hole_node_start(prev_node); | |
575 | + adj_end = hole_end = drm_mm_hole_node_end(prev_node); | |
575 | 576 | |
576 | - adj_start = hole_start; | |
577 | - adj_end = hole_end; | |
578 | - | |
579 | - if (mm->color_adjust) | |
580 | - mm->color_adjust(prev_node, mm->scan_color, &adj_start, &adj_end); | |
581 | - | |
582 | 577 | if (mm->scan_check_range) { |
583 | 578 | if (adj_start < mm->scan_start) |
584 | 579 | adj_start = mm->scan_start; |
585 | 580 | |
... | ... | @@ -586,11 +581,14 @@ |
586 | 581 | adj_end = mm->scan_end; |
587 | 582 | } |
588 | 583 | |
584 | + if (mm->color_adjust) | |
585 | + mm->color_adjust(prev_node, mm->scan_color, | |
586 | + &adj_start, &adj_end); | |
587 | + | |
589 | 588 | if (check_free_hole(adj_start, adj_end, |
590 | 589 | mm->scan_size, mm->scan_alignment)) { |
591 | 590 | mm->scan_hit_start = hole_start; |
592 | - mm->scan_hit_size = hole_end; | |
593 | - | |
591 | + mm->scan_hit_end = hole_end; | |
594 | 592 | return 1; |
595 | 593 | } |
596 | 594 | |
597 | 595 | |
... | ... | @@ -626,19 +624,10 @@ |
626 | 624 | node_list); |
627 | 625 | |
628 | 626 | prev_node->hole_follows = node->scanned_preceeds_hole; |
629 | - INIT_LIST_HEAD(&node->node_list); | |
630 | 627 | list_add(&node->node_list, &prev_node->node_list); |
631 | 628 | |
632 | - /* Only need to check for containement because start&size for the | |
633 | - * complete resulting free block (not just the desired part) is | |
634 | - * stored. */ | |
635 | - if (node->start >= mm->scan_hit_start && | |
636 | - node->start + node->size | |
637 | - <= mm->scan_hit_start + mm->scan_hit_size) { | |
638 | - return 1; | |
639 | - } | |
640 | - | |
641 | - return 0; | |
629 | + return (drm_mm_hole_node_end(node) > mm->scan_hit_start && | |
630 | + node->start < mm->scan_hit_end); | |
642 | 631 | } |
643 | 632 | EXPORT_SYMBOL(drm_mm_scan_remove_block); |
644 | 633 |
include/drm/drm_mm.h