Loading drivers/gpu/msm/adreno_ringbuffer.c +1 −1 Original line number Diff line number Diff line Loading @@ -308,7 +308,7 @@ int adreno_ringbuffer_probe(struct adreno_device *adreno_dev) if (!adreno_is_a3xx(adreno_dev)) { status = kgsl_allocate_global(device, &device->scratch, PAGE_SIZE, 0, 0, "scratch"); PAGE_SIZE, 0, KGSL_MEMDESC_RANDOM, "scratch"); if (status != 0) return status; } Loading drivers/gpu/msm/kgsl.h +2 −0 Original line number Diff line number Diff line Loading @@ -186,6 +186,8 @@ struct kgsl_memdesc_ops { #define KGSL_MEMDESC_CONTIG BIT(8) /* This is an instruction buffer */ #define KGSL_MEMDESC_UCODE BIT(9) /* For global buffers, randomly assign an address from the region */ #define KGSL_MEMDESC_RANDOM BIT(10) /** * struct kgsl_memdesc - GPU memory object descriptor Loading drivers/gpu/msm/kgsl_iommu.c +44 −16 Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ #include <linux/of_platform.h> #include <linux/seq_file.h> #include <linux/delay.h> #include <linux/random.h> #include <soc/qcom/scm.h> #include <soc/qcom/secure_buffer.h> Loading Loading @@ -75,15 +76,8 @@ static struct kmem_cache *addr_entry_cache; * * Here we define an array and a simple allocator to keep track of the currently * active global entries. Each entry is assigned a unique address inside of a * MMU implementation specific "global" region. The addresses are assigned * sequentially and never re-used to avoid having to go back and reprogram * existing pagetables. The entire list of active entries are mapped and * unmapped into every new pagetable as it is created and destroyed. * * Because there are relatively few entries and they are defined at boot time we * don't need to go over the top to define a dynamic allocation scheme. It will * be less wasteful to pick a static number with a little bit of growth * potential. * MMU implementation specific "global" region. We use a simple bitmap based * allocator for the region to allow for both fixed and dynamic addressing. */ #define GLOBAL_PT_ENTRIES 32 Loading @@ -93,12 +87,16 @@ struct global_pt_entry { char name[32]; }; #define GLOBAL_MAP_PAGES (KGSL_IOMMU_GLOBAL_MEM_SIZE >> PAGE_SHIFT) static struct global_pt_entry global_pt_entries[GLOBAL_PT_ENTRIES]; static DECLARE_BITMAP(global_map, GLOBAL_MAP_PAGES); static int secure_global_size; static int global_pt_count; uint64_t global_pt_alloc; static struct kgsl_memdesc gpu_qdss_desc; static struct kgsl_memdesc gpu_qtimer_desc; void kgsl_print_global_pt_entries(struct seq_file *s) { int i; Loading Loading @@ -193,6 +191,12 @@ static void kgsl_iommu_remove_global(struct kgsl_mmu *mmu, for (i = 0; i < global_pt_count; i++) { if (global_pt_entries[i].memdesc == memdesc) { u64 offset = memdesc->gpuaddr - KGSL_IOMMU_GLOBAL_MEM_BASE(mmu); bitmap_clear(global_map, offset >> PAGE_SHIFT, kgsl_memdesc_footprint(memdesc) >> PAGE_SHIFT); memdesc->gpuaddr = 0; memdesc->priv &= ~KGSL_MEMDESC_GLOBAL; global_pt_entries[i].memdesc = NULL; Loading @@ -204,19 +208,43 @@ static void kgsl_iommu_remove_global(struct kgsl_mmu *mmu, static void kgsl_iommu_add_global(struct kgsl_mmu *mmu, struct kgsl_memdesc *memdesc, const char *name) { u32 bit, start = 0; u64 size = kgsl_memdesc_footprint(memdesc); if (memdesc->gpuaddr != 0) return; /*Check that we can fit the global allocations */ if (WARN_ON(global_pt_count >= GLOBAL_PT_ENTRIES) || WARN_ON((global_pt_alloc + memdesc->size) >= KGSL_IOMMU_GLOBAL_MEM_SIZE)) if (WARN_ON(global_pt_count >= GLOBAL_PT_ENTRIES)) return; if (WARN_ON(size > KGSL_IOMMU_GLOBAL_MEM_SIZE)) return; if (memdesc->priv & KGSL_MEMDESC_RANDOM) { u32 range = GLOBAL_MAP_PAGES - (size >> PAGE_SHIFT); start = get_random_int() % range; } while (start >= 0) { bit = bitmap_find_next_zero_area(global_map, GLOBAL_MAP_PAGES, start, size >> PAGE_SHIFT, 0); if (bit < GLOBAL_MAP_PAGES) break; start--; } if (WARN_ON(start < 0)) return; memdesc->gpuaddr = KGSL_IOMMU_GLOBAL_MEM_BASE(mmu) + global_pt_alloc; memdesc->gpuaddr = KGSL_IOMMU_GLOBAL_MEM_BASE(mmu) + (bit << PAGE_SHIFT); bitmap_set(global_map, bit, size >> PAGE_SHIFT); memdesc->priv |= KGSL_MEMDESC_GLOBAL; global_pt_alloc += kgsl_memdesc_footprint(memdesc); global_pt_entries[global_pt_count].memdesc = memdesc; strlcpy(global_pt_entries[global_pt_count].name, name, Loading Loading
drivers/gpu/msm/adreno_ringbuffer.c +1 −1 Original line number Diff line number Diff line Loading @@ -308,7 +308,7 @@ int adreno_ringbuffer_probe(struct adreno_device *adreno_dev) if (!adreno_is_a3xx(adreno_dev)) { status = kgsl_allocate_global(device, &device->scratch, PAGE_SIZE, 0, 0, "scratch"); PAGE_SIZE, 0, KGSL_MEMDESC_RANDOM, "scratch"); if (status != 0) return status; } Loading
drivers/gpu/msm/kgsl.h +2 −0 Original line number Diff line number Diff line Loading @@ -186,6 +186,8 @@ struct kgsl_memdesc_ops { #define KGSL_MEMDESC_CONTIG BIT(8) /* This is an instruction buffer */ #define KGSL_MEMDESC_UCODE BIT(9) /* For global buffers, randomly assign an address from the region */ #define KGSL_MEMDESC_RANDOM BIT(10) /** * struct kgsl_memdesc - GPU memory object descriptor Loading
drivers/gpu/msm/kgsl_iommu.c +44 −16 Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ #include <linux/of_platform.h> #include <linux/seq_file.h> #include <linux/delay.h> #include <linux/random.h> #include <soc/qcom/scm.h> #include <soc/qcom/secure_buffer.h> Loading Loading @@ -75,15 +76,8 @@ static struct kmem_cache *addr_entry_cache; * * Here we define an array and a simple allocator to keep track of the currently * active global entries. Each entry is assigned a unique address inside of a * MMU implementation specific "global" region. The addresses are assigned * sequentially and never re-used to avoid having to go back and reprogram * existing pagetables. The entire list of active entries are mapped and * unmapped into every new pagetable as it is created and destroyed. * * Because there are relatively few entries and they are defined at boot time we * don't need to go over the top to define a dynamic allocation scheme. It will * be less wasteful to pick a static number with a little bit of growth * potential. * MMU implementation specific "global" region. We use a simple bitmap based * allocator for the region to allow for both fixed and dynamic addressing. */ #define GLOBAL_PT_ENTRIES 32 Loading @@ -93,12 +87,16 @@ struct global_pt_entry { char name[32]; }; #define GLOBAL_MAP_PAGES (KGSL_IOMMU_GLOBAL_MEM_SIZE >> PAGE_SHIFT) static struct global_pt_entry global_pt_entries[GLOBAL_PT_ENTRIES]; static DECLARE_BITMAP(global_map, GLOBAL_MAP_PAGES); static int secure_global_size; static int global_pt_count; uint64_t global_pt_alloc; static struct kgsl_memdesc gpu_qdss_desc; static struct kgsl_memdesc gpu_qtimer_desc; void kgsl_print_global_pt_entries(struct seq_file *s) { int i; Loading Loading @@ -193,6 +191,12 @@ static void kgsl_iommu_remove_global(struct kgsl_mmu *mmu, for (i = 0; i < global_pt_count; i++) { if (global_pt_entries[i].memdesc == memdesc) { u64 offset = memdesc->gpuaddr - KGSL_IOMMU_GLOBAL_MEM_BASE(mmu); bitmap_clear(global_map, offset >> PAGE_SHIFT, kgsl_memdesc_footprint(memdesc) >> PAGE_SHIFT); memdesc->gpuaddr = 0; memdesc->priv &= ~KGSL_MEMDESC_GLOBAL; global_pt_entries[i].memdesc = NULL; Loading @@ -204,19 +208,43 @@ static void kgsl_iommu_remove_global(struct kgsl_mmu *mmu, static void kgsl_iommu_add_global(struct kgsl_mmu *mmu, struct kgsl_memdesc *memdesc, const char *name) { u32 bit, start = 0; u64 size = kgsl_memdesc_footprint(memdesc); if (memdesc->gpuaddr != 0) return; /*Check that we can fit the global allocations */ if (WARN_ON(global_pt_count >= GLOBAL_PT_ENTRIES) || WARN_ON((global_pt_alloc + memdesc->size) >= KGSL_IOMMU_GLOBAL_MEM_SIZE)) if (WARN_ON(global_pt_count >= GLOBAL_PT_ENTRIES)) return; if (WARN_ON(size > KGSL_IOMMU_GLOBAL_MEM_SIZE)) return; if (memdesc->priv & KGSL_MEMDESC_RANDOM) { u32 range = GLOBAL_MAP_PAGES - (size >> PAGE_SHIFT); start = get_random_int() % range; } while (start >= 0) { bit = bitmap_find_next_zero_area(global_map, GLOBAL_MAP_PAGES, start, size >> PAGE_SHIFT, 0); if (bit < GLOBAL_MAP_PAGES) break; start--; } if (WARN_ON(start < 0)) return; memdesc->gpuaddr = KGSL_IOMMU_GLOBAL_MEM_BASE(mmu) + global_pt_alloc; memdesc->gpuaddr = KGSL_IOMMU_GLOBAL_MEM_BASE(mmu) + (bit << PAGE_SHIFT); bitmap_set(global_map, bit, size >> PAGE_SHIFT); memdesc->priv |= KGSL_MEMDESC_GLOBAL; global_pt_alloc += kgsl_memdesc_footprint(memdesc); global_pt_entries[global_pt_count].memdesc = memdesc; strlcpy(global_pt_entries[global_pt_count].name, name, Loading