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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'drm-x86-pat-regression-fix' of git://people.freedesktop.org/~airlied/linux

Pull drm x86/pat regression fixes from Dave Airlie:
"This is a standalone pull request for the fix for a regression
introduced in -rc1 by a change to vm_insert_mixed to start using the
PAT range tracking to validate page protections. With this fix in
place, all the VRAM mappings for GPU drivers ended up at UC instead of
WC.

There are probably better ways to fix this long term, but nothing I'd
considered for -fixes that wouldn't need more settling in time. So
I've just created a new arch API that the drivers can reserve all
their VRAM aperture ranges as WC"

* tag 'drm-x86-pat-regression-fix' of git://people.freedesktop.org/~airlied/linux:
drm/drivers: add support for using the arch wc mapping API.
x86/io: add interface to reserve io memtype for a resource range. (v1.1)

+80
+6
arch/x86/include/asm/io.h
··· 351 351 #define arch_phys_wc_add arch_phys_wc_add 352 352 #endif 353 353 354 + #ifdef CONFIG_X86_PAT 355 + extern int arch_io_reserve_memtype_wc(resource_size_t start, resource_size_t size); 356 + extern void arch_io_free_memtype_wc(resource_size_t start, resource_size_t size); 357 + #define arch_io_reserve_memtype_wc arch_io_reserve_memtype_wc 358 + #endif 359 + 354 360 #endif /* _ASM_X86_IO_H */
+14
arch/x86/mm/pat.c
··· 730 730 free_memtype(start, end); 731 731 } 732 732 733 + int arch_io_reserve_memtype_wc(resource_size_t start, resource_size_t size) 734 + { 735 + enum page_cache_mode type = _PAGE_CACHE_MODE_WC; 736 + 737 + return io_reserve_memtype(start, start + size, &type); 738 + } 739 + EXPORT_SYMBOL(arch_io_reserve_memtype_wc); 740 + 741 + void arch_io_free_memtype_wc(resource_size_t start, resource_size_t size) 742 + { 743 + io_free_memtype(start, start + size); 744 + } 745 + EXPORT_SYMBOL(arch_io_free_memtype_wc); 746 + 733 747 pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, 734 748 unsigned long size, pgprot_t vma_prot) 735 749 {
+5
drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
··· 754 754 755 755 int amdgpu_bo_init(struct amdgpu_device *adev) 756 756 { 757 + /* reserve PAT memory space to WC for VRAM */ 758 + arch_io_reserve_memtype_wc(adev->mc.aper_base, 759 + adev->mc.aper_size); 760 + 757 761 /* Add an MTRR for the VRAM */ 758 762 adev->mc.vram_mtrr = arch_phys_wc_add(adev->mc.aper_base, 759 763 adev->mc.aper_size); ··· 773 769 { 774 770 amdgpu_ttm_fini(adev); 775 771 arch_phys_wc_del(adev->mc.vram_mtrr); 772 + arch_io_free_memtype_wc(adev->mc.aper_base, adev->mc.aper_size); 776 773 } 777 774 778 775 int amdgpu_bo_fbdev_mmap(struct amdgpu_bo *bo,
+6
drivers/gpu/drm/ast/ast_ttm.c
··· 267 267 return ret; 268 268 } 269 269 270 + arch_io_reserve_memtype_wc(pci_resource_start(dev->pdev, 0), 271 + pci_resource_len(dev->pdev, 0)); 270 272 ast->fb_mtrr = arch_phys_wc_add(pci_resource_start(dev->pdev, 0), 271 273 pci_resource_len(dev->pdev, 0)); 272 274 ··· 277 275 278 276 void ast_mm_fini(struct ast_private *ast) 279 277 { 278 + struct drm_device *dev = ast->dev; 279 + 280 280 ttm_bo_device_release(&ast->ttm.bdev); 281 281 282 282 ast_ttm_global_release(ast); 283 283 284 284 arch_phys_wc_del(ast->fb_mtrr); 285 + arch_io_free_memtype_wc(pci_resource_start(dev->pdev, 0), 286 + pci_resource_len(dev->pdev, 0)); 285 287 } 286 288 287 289 void ast_ttm_placement(struct ast_bo *bo, int domain)
+7
drivers/gpu/drm/cirrus/cirrus_ttm.c
··· 267 267 return ret; 268 268 } 269 269 270 + arch_io_reserve_memtype_wc(pci_resource_start(dev->pdev, 0), 271 + pci_resource_len(dev->pdev, 0)); 272 + 270 273 cirrus->fb_mtrr = arch_phys_wc_add(pci_resource_start(dev->pdev, 0), 271 274 pci_resource_len(dev->pdev, 0)); 272 275 ··· 279 276 280 277 void cirrus_mm_fini(struct cirrus_device *cirrus) 281 278 { 279 + struct drm_device *dev = cirrus->dev; 280 + 282 281 if (!cirrus->mm_inited) 283 282 return; 284 283 ··· 290 285 291 286 arch_phys_wc_del(cirrus->fb_mtrr); 292 287 cirrus->fb_mtrr = 0; 288 + arch_io_free_memtype_wc(pci_resource_start(dev->pdev, 0), 289 + pci_resource_len(dev->pdev, 0)); 293 290 } 294 291 295 292 void cirrus_ttm_placement(struct cirrus_bo *bo, int domain)
+7
drivers/gpu/drm/mgag200/mgag200_ttm.c
··· 266 266 return ret; 267 267 } 268 268 269 + arch_io_reserve_memtype_wc(pci_resource_start(dev->pdev, 0), 270 + pci_resource_len(dev->pdev, 0)); 271 + 269 272 mdev->fb_mtrr = arch_phys_wc_add(pci_resource_start(dev->pdev, 0), 270 273 pci_resource_len(dev->pdev, 0)); 271 274 ··· 277 274 278 275 void mgag200_mm_fini(struct mga_device *mdev) 279 276 { 277 + struct drm_device *dev = mdev->dev; 278 + 280 279 ttm_bo_device_release(&mdev->ttm.bdev); 281 280 282 281 mgag200_ttm_global_release(mdev); 283 282 283 + arch_io_free_memtype_wc(pci_resource_start(dev->pdev, 0), 284 + pci_resource_len(dev->pdev, 0)); 284 285 arch_phys_wc_del(mdev->fb_mtrr); 285 286 mdev->fb_mtrr = 0; 286 287 }
+8
drivers/gpu/drm/nouveau/nouveau_ttm.c
··· 398 398 /* VRAM init */ 399 399 drm->gem.vram_available = drm->device.info.ram_user; 400 400 401 + arch_io_reserve_memtype_wc(device->func->resource_addr(device, 1), 402 + device->func->resource_size(device, 1)); 403 + 401 404 ret = ttm_bo_init_mm(&drm->ttm.bdev, TTM_PL_VRAM, 402 405 drm->gem.vram_available >> PAGE_SHIFT); 403 406 if (ret) { ··· 433 430 void 434 431 nouveau_ttm_fini(struct nouveau_drm *drm) 435 432 { 433 + struct nvkm_device *device = nvxx_device(&drm->device); 434 + 436 435 ttm_bo_clean_mm(&drm->ttm.bdev, TTM_PL_VRAM); 437 436 ttm_bo_clean_mm(&drm->ttm.bdev, TTM_PL_TT); 438 437 ··· 444 439 445 440 arch_phys_wc_del(drm->ttm.mtrr); 446 441 drm->ttm.mtrr = 0; 442 + arch_io_free_memtype_wc(device->func->resource_addr(device, 1), 443 + device->func->resource_size(device, 1)); 444 + 447 445 }
+5
drivers/gpu/drm/radeon/radeon_object.c
··· 446 446 447 447 int radeon_bo_init(struct radeon_device *rdev) 448 448 { 449 + /* reserve PAT memory space to WC for VRAM */ 450 + arch_io_reserve_memtype_wc(rdev->mc.aper_base, 451 + rdev->mc.aper_size); 452 + 449 453 /* Add an MTRR for the VRAM */ 450 454 if (!rdev->fastfb_working) { 451 455 rdev->mc.vram_mtrr = arch_phys_wc_add(rdev->mc.aper_base, ··· 467 463 { 468 464 radeon_ttm_fini(rdev); 469 465 arch_phys_wc_del(rdev->mc.vram_mtrr); 466 + arch_io_free_memtype_wc(rdev->mc.aper_base, rdev->mc.aper_size); 470 467 } 471 468 472 469 /* Returns how many bytes TTM can move per IB.
+22
include/linux/io.h
··· 141 141 void *memremap(resource_size_t offset, size_t size, unsigned long flags); 142 142 void memunmap(void *addr); 143 143 144 + /* 145 + * On x86 PAT systems we have memory tracking that keeps track of 146 + * the allowed mappings on memory ranges. This tracking works for 147 + * all the in-kernel mapping APIs (ioremap*), but where the user 148 + * wishes to map a range from a physical device into user memory 149 + * the tracking won't be updated. This API is to be used by 150 + * drivers which remap physical device pages into userspace, 151 + * and wants to make sure they are mapped WC and not UC. 152 + */ 153 + #ifndef arch_io_reserve_memtype_wc 154 + static inline int arch_io_reserve_memtype_wc(resource_size_t base, 155 + resource_size_t size) 156 + { 157 + return 0; 158 + } 159 + 160 + static inline void arch_io_free_memtype_wc(resource_size_t base, 161 + resource_size_t size) 162 + { 163 + } 164 + #endif 165 + 144 166 #endif /* _LINUX_IO_H */