X-Git-Url: http://git.cascardo.eti.br/?a=blobdiff_plain;f=mm%2Fshmem.c;h=e0cec1ac18612e72a75c73dc3459f0c63d91b49c;hb=05f161898c3a14807ceda9a53ae8b2c3ba2114c3;hp=f99ff3e50bd6af061b30722528d002bab68e6e40;hpb=73bebc8bafb6a880a4db63d60bc4b8d9d6879c9e;p=cascardo%2Flinux.git diff --git a/mm/shmem.c b/mm/shmem.c index f99ff3e50bd6..e0cec1ac1861 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -768,6 +768,31 @@ redirty: return 0; } +/* + * Some intel GPUs can't use those pages in the GTT, which results in + * graphics corruption. Sadly, it's impossible to prevent usage of those + * pages in the intel allocator. + * + * Instead, we test for those areas here and leak the corresponding pages. + * + * Some day, when the intel GPU memory is not backed by shmem any more, + * we'll be able to come up with a solution which is contained in i915. + */ +static bool i915_usable_page(struct page *page) +{ + dma_addr_t addr = page_to_phys(page); + + if (unlikely((addr < 1 * 1024 * 1024) || + (addr == 0x20050000) || + (addr == 0x20110000) || + (addr == 0x20130000) || + (addr == 0x20138000) || + (addr == 0x40004000))) + return false; + + return true; +} + #ifdef CONFIG_NUMA #ifdef CONFIG_TMPFS static void shmem_show_mpol(struct seq_file *seq, struct mempolicy *mpol) @@ -816,6 +841,7 @@ static struct page *shmem_alloc_page(gfp_t gfp, struct shmem_inode_info *info, pgoff_t index) { struct vm_area_struct pvma; + struct page *page; /* Create a pseudo vma that just contains the policy */ pvma.vm_start = 0; @@ -826,7 +852,11 @@ static struct page *shmem_alloc_page(gfp_t gfp, /* * alloc_page_vma() will drop the shared policy reference */ - return alloc_page_vma(gfp, &pvma, 0); + do { + page = alloc_page_vma(gfp, &pvma, 0); + } while (page && !i915_usable_page(page)); + + return page; } #else /* !CONFIG_NUMA */ #ifdef CONFIG_TMPFS @@ -844,7 +874,12 @@ static inline struct page *shmem_swapin(swp_entry_t swap, gfp_t gfp, static inline struct page *shmem_alloc_page(gfp_t gfp, struct shmem_inode_info *info, pgoff_t index) { - return alloc_page(gfp); + struct page *page; + do { + page = alloc_page(gfp); + } while (page && !i915_usable_page(page)); + + return page; } #endif /* CONFIG_NUMA */