Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/ttm: Fix memory space allocation v2

In the event that TTM doesn't find a compatible memory type for the
driver's first placement choice (placement without eviction), TTM
returns -EINVAL without trying the driver's second choice.
This causes problems on vmwgfx when VRAM is disabled before first modeset
and during VT switches when fbdev is not enabled.

Fix this by also trying the driver's second choice before returning
-EINVAL.

v2: Also check that man->use_type is true for the driver's second choice.
Fixes a bug where disallowed memory types could be used.

Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
Reviewed-by: Brian Paul <brianp@vmware.com>
Reviewed-by: Sinclair Yeh <syeh@vmware.com>

+16 -12
+16 -12
drivers/gpu/drm/ttm/ttm_bo.c
··· 882 882 if (ret) 883 883 return ret; 884 884 man = &bdev->man[mem_type]; 885 + if (!man->has_type || !man->use_type) 886 + continue; 885 887 886 888 type_ok = ttm_bo_mt_compatible(man, mem_type, place, 887 889 &cur_flags); ··· 891 889 if (!type_ok) 892 890 continue; 893 891 892 + type_found = true; 894 893 cur_flags = ttm_bo_select_caching(man, bo->mem.placement, 895 894 cur_flags); 896 895 /* ··· 904 901 if (mem_type == TTM_PL_SYSTEM) 905 902 break; 906 903 907 - if (man->has_type && man->use_type) { 908 - type_found = true; 909 - ret = (*man->func->get_node)(man, bo, place, mem); 910 - if (unlikely(ret)) 911 - return ret; 912 - } 904 + ret = (*man->func->get_node)(man, bo, place, mem); 905 + if (unlikely(ret)) 906 + return ret; 907 + 913 908 if (mem->mm_node) 914 909 break; 915 910 } ··· 918 917 return 0; 919 918 } 920 919 921 - if (!type_found) 922 - return -EINVAL; 923 - 924 920 for (i = 0; i < placement->num_busy_placement; ++i) { 925 921 const struct ttm_place *place = &placement->busy_placement[i]; 926 922 ··· 925 927 if (ret) 926 928 return ret; 927 929 man = &bdev->man[mem_type]; 928 - if (!man->has_type) 930 + if (!man->has_type || !man->use_type) 929 931 continue; 930 932 if (!ttm_bo_mt_compatible(man, mem_type, place, &cur_flags)) 931 933 continue; 932 934 935 + type_found = true; 933 936 cur_flags = ttm_bo_select_caching(man, bo->mem.placement, 934 937 cur_flags); 935 938 /* ··· 956 957 if (ret == -ERESTARTSYS) 957 958 has_erestartsys = true; 958 959 } 959 - ret = (has_erestartsys) ? -ERESTARTSYS : -ENOMEM; 960 - return ret; 960 + 961 + if (!type_found) { 962 + printk(KERN_ERR TTM_PFX "No compatible memory type found.\n"); 963 + return -EINVAL; 964 + } 965 + 966 + return (has_erestartsys) ? -ERESTARTSYS : -ENOMEM; 961 967 } 962 968 EXPORT_SYMBOL(ttm_bo_mem_space); 963 969