Loading drivers/gpu/msm/adreno_snapshot.c +2 −2 Original line number Diff line number Diff line Loading @@ -738,7 +738,7 @@ static void setup_fault_process(struct kgsl_device *device, if (kgsl_mmu_is_perprocess(&device->mmu)) { struct kgsl_process_private *tmp; mutex_lock(&kgsl_driver.process_mutex); spin_lock(&kgsl_driver.proclist_lock); list_for_each_entry(tmp, &kgsl_driver.process_list, list) { u64 pt_ttbr0; Loading @@ -749,7 +749,7 @@ static void setup_fault_process(struct kgsl_device *device, break; } } mutex_unlock(&kgsl_driver.process_mutex); spin_unlock(&kgsl_driver.proclist_lock); } done: snapshot->process = process; Loading drivers/gpu/msm/kgsl.c +8 −2 Original line number Diff line number Diff line Loading @@ -921,7 +921,7 @@ struct kgsl_process_private *kgsl_process_private_find(pid_t pid) { struct kgsl_process_private *p, *private = NULL; mutex_lock(&kgsl_driver.process_mutex); spin_lock(&kgsl_driver.proclist_lock); list_for_each_entry(p, &kgsl_driver.process_list, list) { if (p->pid == pid) { if (kgsl_process_private_get(p)) Loading @@ -929,7 +929,8 @@ struct kgsl_process_private *kgsl_process_private_find(pid_t pid) break; } } mutex_unlock(&kgsl_driver.process_mutex); spin_unlock(&kgsl_driver.proclist_lock); return private; } Loading Loading @@ -1035,7 +1036,9 @@ static void kgsl_process_private_close(struct kgsl_device_private *dev_priv, kgsl_mmu_detach_pagetable(private->pagetable); /* Remove the process struct from the master list */ spin_lock(&kgsl_driver.proclist_lock); list_del(&private->list); spin_unlock(&kgsl_driver.proclist_lock); /* * Unlock the mutex before releasing the memory and the debugfs Loading Loading @@ -1071,7 +1074,9 @@ static struct kgsl_process_private *kgsl_process_private_open( kgsl_process_init_sysfs(device, private); kgsl_process_init_debugfs(private); spin_lock(&kgsl_driver.proclist_lock); list_add(&private->list, &kgsl_driver.process_list); spin_unlock(&kgsl_driver.proclist_lock); } done: Loading Loading @@ -4870,6 +4875,7 @@ static const struct file_operations kgsl_fops = { struct kgsl_driver kgsl_driver = { .process_mutex = __MUTEX_INITIALIZER(kgsl_driver.process_mutex), .proclist_lock = __SPIN_LOCK_UNLOCKED(kgsl_driver.proclist_lock), .ptlock = __SPIN_LOCK_UNLOCKED(kgsl_driver.ptlock), .devlock = __MUTEX_INITIALIZER(kgsl_driver.devlock), /* Loading drivers/gpu/msm/kgsl.h +2 −0 Original line number Diff line number Diff line Loading @@ -113,6 +113,7 @@ struct kgsl_context; * @pagetable_list: LIst of open pagetables * @ptlock: Lock for accessing the pagetable list * @process_mutex: Mutex for accessing the process list * @proclist_lock: Lock for accessing the process list * @devlock: Mutex protecting the device list * @stats: Struct containing atomic memory statistics * @full_cache_threshold: the threshold that triggers a full cache flush Loading @@ -131,6 +132,7 @@ struct kgsl_driver { struct list_head pagetable_list; spinlock_t ptlock; struct mutex process_mutex; spinlock_t proclist_lock; struct mutex devlock; struct { atomic_long_t vmalloc; Loading drivers/gpu/msm/kgsl_iommu.c +44 −59 Original line number Diff line number Diff line Loading @@ -635,10 +635,8 @@ static void _get_entries(struct kgsl_process_private *private, static void _find_mem_entries(struct kgsl_mmu *mmu, uint64_t faultaddr, struct _mem_entry *preventry, struct _mem_entry *nextentry, struct kgsl_context *context) struct kgsl_process_private *private) { struct kgsl_process_private *private; memset(preventry, 0, sizeof(*preventry)); memset(nextentry, 0, sizeof(*nextentry)); Loading @@ -647,8 +645,7 @@ static void _find_mem_entries(struct kgsl_mmu *mmu, uint64_t faultaddr, if (ADDR_IN_GLOBAL(mmu, faultaddr)) { _get_global_entries(faultaddr, preventry, nextentry); } else if (context) { private = context->proc_priv; } else if (private) { spin_lock(&private->mem_lock); _get_entries(private, faultaddr, preventry, nextentry); spin_unlock(&private->mem_lock); Loading Loading @@ -687,6 +684,29 @@ static void _check_if_freed(struct kgsl_iommu_context *ctx, } } static struct kgsl_process_private *kgsl_iommu_get_process(u64 ptbase) { struct kgsl_process_private *p; struct kgsl_iommu_pt *iommu_pt; spin_lock(&kgsl_driver.proclist_lock); list_for_each_entry(p, &kgsl_driver.process_list, list) { iommu_pt = p->pagetable->priv; if (iommu_pt->ttbr0 == ptbase) { if (!kgsl_process_private_get(p)) p = NULL; spin_unlock(&kgsl_driver.proclist_lock); return p; } } spin_unlock(&kgsl_driver.proclist_lock); return NULL; } static int kgsl_iommu_fault_handler(struct iommu_domain *domain, struct device *dev, unsigned long addr, int flags, void *token) { Loading @@ -695,7 +715,7 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain, struct kgsl_mmu *mmu = pt->mmu; struct kgsl_iommu *iommu; struct kgsl_iommu_context *ctx; u64 ptbase, proc_ptbase; u64 ptbase; u32 contextidr; pid_t pid = 0; pid_t ptname; Loading @@ -705,9 +725,9 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain, struct adreno_device *adreno_dev; struct adreno_gpudev *gpudev; unsigned int no_page_fault_log = 0; unsigned int curr_context_id = 0; struct kgsl_context *context; char *fault_type = "unknown"; char *comm = "unknown"; struct kgsl_process_private *private; static DEFINE_RATELIMIT_STATE(_rs, DEFAULT_RATELIMIT_INTERVAL, Loading @@ -722,21 +742,6 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain, adreno_dev = ADRENO_DEVICE(device); gpudev = ADRENO_GPU_DEVICE(adreno_dev); if (pt->name == KGSL_MMU_SECURE_PT) ctx = &iommu->ctx[KGSL_IOMMU_CONTEXT_SECURE]; /* * set the fault bits and stuff before any printks so that if fault * handler runs then it will know it's dealing with a pagefault. * Read the global current timestamp because we could be in middle of * RB switch and hence the cur RB may not be reliable but global * one will always be reliable */ kgsl_sharedmem_readl(&device->memstore, &curr_context_id, KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context)); context = kgsl_context_get(device, curr_context_id); write = (flags & IOMMU_FAULT_WRITE) ? 1 : 0; if (flags & IOMMU_FAULT_TRANSLATION) fault_type = "translation"; Loading @@ -747,12 +752,17 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain, else if (flags & IOMMU_FAULT_TRANSACTION_STALLED) fault_type = "transaction stalled"; if (context != NULL) { /* save pagefault timestamp for GFT */ set_bit(KGSL_CONTEXT_PRIV_PAGEFAULT, &context->priv); pid = context->proc_priv->pid; ptbase = KGSL_IOMMU_GET_CTX_REG_Q(ctx, TTBR0); private = kgsl_iommu_get_process(ptbase); if (private) { pid = private->pid; comm = private->comm; } if (pt->name == KGSL_MMU_SECURE_PT) ctx = &iommu->ctx[KGSL_IOMMU_CONTEXT_SECURE]; ctx->fault = 1; if (test_bit(KGSL_FT_PAGEFAULT_GPUHALT_ENABLE, Loading @@ -767,9 +777,7 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain, mutex_unlock(&device->mutex); } ptbase = KGSL_IOMMU_GET_CTX_REG_Q(ctx, TTBR0); contextidr = KGSL_IOMMU_GET_CTX_REG(ctx, CONTEXTIDR); ptname = MMU_FEATURE(mmu, KGSL_MMU_GLOBAL_PAGETABLE) ? KGSL_MMU_GLOBAL_PT : pid; /* Loading @@ -778,43 +786,19 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain, * search and delays the trace unnecessarily. */ trace_kgsl_mmu_pagefault(ctx->kgsldev, addr, ptname, context != NULL ? context->proc_priv->comm : "unknown", write ? "write" : "read"); ptname, comm, write ? "write" : "read"); if (test_bit(KGSL_FT_PAGEFAULT_LOG_ONE_PER_PAGE, &adreno_dev->ft_pf_policy)) no_page_fault_log = kgsl_mmu_log_fault_addr(mmu, ptbase, addr); if (!no_page_fault_log && __ratelimit(&_rs)) { const char *api_str; if (context != NULL) { struct adreno_context *drawctxt = ADRENO_CONTEXT(context); api_str = get_api_type_str(drawctxt->type); } else api_str = "UNKNOWN"; dev_crit(ctx->kgsldev->dev, "GPU PAGE FAULT: addr = %lX pid= %d name=%s\n", addr, ptname, context != NULL ? context->proc_priv->comm : "unknown"); if (context != NULL) { proc_ptbase = kgsl_mmu_pagetable_get_ttbr0( context->proc_priv->pagetable); if (ptbase != proc_ptbase) ptname, comm); dev_crit(ctx->kgsldev->dev, "Pagetable address mismatch: HW address is 0x%llx but SW expected 0x%llx\n", ptbase, proc_ptbase); } dev_crit(ctx->kgsldev->dev, "context=%s ctx_type=%s TTBR0=0x%llx CIDR=0x%x (%s %s fault)\n", ctx->name, api_str, ptbase, contextidr, "context=%s TTBR0=0x%llx CIDR=0x%x (%s %s fault)\n", ctx->name, ptbase, contextidr, write ? "write" : "read", fault_type); if (gpudev->iommu_fault_block) { Loading @@ -834,7 +818,7 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain, dev_err(ctx->kgsldev->dev, "---- nearby memory ----\n"); _find_mem_entries(mmu, addr, &prev, &next, context); _find_mem_entries(mmu, addr, &prev, &next, private); if (prev.gpuaddr) _print_entry(ctx->kgsldev, &prev); else Loading Loading @@ -877,7 +861,8 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain, adreno_dispatcher_schedule(device); } kgsl_context_put(context); kgsl_process_private_put(private); return ret; } Loading Loading
drivers/gpu/msm/adreno_snapshot.c +2 −2 Original line number Diff line number Diff line Loading @@ -738,7 +738,7 @@ static void setup_fault_process(struct kgsl_device *device, if (kgsl_mmu_is_perprocess(&device->mmu)) { struct kgsl_process_private *tmp; mutex_lock(&kgsl_driver.process_mutex); spin_lock(&kgsl_driver.proclist_lock); list_for_each_entry(tmp, &kgsl_driver.process_list, list) { u64 pt_ttbr0; Loading @@ -749,7 +749,7 @@ static void setup_fault_process(struct kgsl_device *device, break; } } mutex_unlock(&kgsl_driver.process_mutex); spin_unlock(&kgsl_driver.proclist_lock); } done: snapshot->process = process; Loading
drivers/gpu/msm/kgsl.c +8 −2 Original line number Diff line number Diff line Loading @@ -921,7 +921,7 @@ struct kgsl_process_private *kgsl_process_private_find(pid_t pid) { struct kgsl_process_private *p, *private = NULL; mutex_lock(&kgsl_driver.process_mutex); spin_lock(&kgsl_driver.proclist_lock); list_for_each_entry(p, &kgsl_driver.process_list, list) { if (p->pid == pid) { if (kgsl_process_private_get(p)) Loading @@ -929,7 +929,8 @@ struct kgsl_process_private *kgsl_process_private_find(pid_t pid) break; } } mutex_unlock(&kgsl_driver.process_mutex); spin_unlock(&kgsl_driver.proclist_lock); return private; } Loading Loading @@ -1035,7 +1036,9 @@ static void kgsl_process_private_close(struct kgsl_device_private *dev_priv, kgsl_mmu_detach_pagetable(private->pagetable); /* Remove the process struct from the master list */ spin_lock(&kgsl_driver.proclist_lock); list_del(&private->list); spin_unlock(&kgsl_driver.proclist_lock); /* * Unlock the mutex before releasing the memory and the debugfs Loading Loading @@ -1071,7 +1074,9 @@ static struct kgsl_process_private *kgsl_process_private_open( kgsl_process_init_sysfs(device, private); kgsl_process_init_debugfs(private); spin_lock(&kgsl_driver.proclist_lock); list_add(&private->list, &kgsl_driver.process_list); spin_unlock(&kgsl_driver.proclist_lock); } done: Loading Loading @@ -4870,6 +4875,7 @@ static const struct file_operations kgsl_fops = { struct kgsl_driver kgsl_driver = { .process_mutex = __MUTEX_INITIALIZER(kgsl_driver.process_mutex), .proclist_lock = __SPIN_LOCK_UNLOCKED(kgsl_driver.proclist_lock), .ptlock = __SPIN_LOCK_UNLOCKED(kgsl_driver.ptlock), .devlock = __MUTEX_INITIALIZER(kgsl_driver.devlock), /* Loading
drivers/gpu/msm/kgsl.h +2 −0 Original line number Diff line number Diff line Loading @@ -113,6 +113,7 @@ struct kgsl_context; * @pagetable_list: LIst of open pagetables * @ptlock: Lock for accessing the pagetable list * @process_mutex: Mutex for accessing the process list * @proclist_lock: Lock for accessing the process list * @devlock: Mutex protecting the device list * @stats: Struct containing atomic memory statistics * @full_cache_threshold: the threshold that triggers a full cache flush Loading @@ -131,6 +132,7 @@ struct kgsl_driver { struct list_head pagetable_list; spinlock_t ptlock; struct mutex process_mutex; spinlock_t proclist_lock; struct mutex devlock; struct { atomic_long_t vmalloc; Loading
drivers/gpu/msm/kgsl_iommu.c +44 −59 Original line number Diff line number Diff line Loading @@ -635,10 +635,8 @@ static void _get_entries(struct kgsl_process_private *private, static void _find_mem_entries(struct kgsl_mmu *mmu, uint64_t faultaddr, struct _mem_entry *preventry, struct _mem_entry *nextentry, struct kgsl_context *context) struct kgsl_process_private *private) { struct kgsl_process_private *private; memset(preventry, 0, sizeof(*preventry)); memset(nextentry, 0, sizeof(*nextentry)); Loading @@ -647,8 +645,7 @@ static void _find_mem_entries(struct kgsl_mmu *mmu, uint64_t faultaddr, if (ADDR_IN_GLOBAL(mmu, faultaddr)) { _get_global_entries(faultaddr, preventry, nextentry); } else if (context) { private = context->proc_priv; } else if (private) { spin_lock(&private->mem_lock); _get_entries(private, faultaddr, preventry, nextentry); spin_unlock(&private->mem_lock); Loading Loading @@ -687,6 +684,29 @@ static void _check_if_freed(struct kgsl_iommu_context *ctx, } } static struct kgsl_process_private *kgsl_iommu_get_process(u64 ptbase) { struct kgsl_process_private *p; struct kgsl_iommu_pt *iommu_pt; spin_lock(&kgsl_driver.proclist_lock); list_for_each_entry(p, &kgsl_driver.process_list, list) { iommu_pt = p->pagetable->priv; if (iommu_pt->ttbr0 == ptbase) { if (!kgsl_process_private_get(p)) p = NULL; spin_unlock(&kgsl_driver.proclist_lock); return p; } } spin_unlock(&kgsl_driver.proclist_lock); return NULL; } static int kgsl_iommu_fault_handler(struct iommu_domain *domain, struct device *dev, unsigned long addr, int flags, void *token) { Loading @@ -695,7 +715,7 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain, struct kgsl_mmu *mmu = pt->mmu; struct kgsl_iommu *iommu; struct kgsl_iommu_context *ctx; u64 ptbase, proc_ptbase; u64 ptbase; u32 contextidr; pid_t pid = 0; pid_t ptname; Loading @@ -705,9 +725,9 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain, struct adreno_device *adreno_dev; struct adreno_gpudev *gpudev; unsigned int no_page_fault_log = 0; unsigned int curr_context_id = 0; struct kgsl_context *context; char *fault_type = "unknown"; char *comm = "unknown"; struct kgsl_process_private *private; static DEFINE_RATELIMIT_STATE(_rs, DEFAULT_RATELIMIT_INTERVAL, Loading @@ -722,21 +742,6 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain, adreno_dev = ADRENO_DEVICE(device); gpudev = ADRENO_GPU_DEVICE(adreno_dev); if (pt->name == KGSL_MMU_SECURE_PT) ctx = &iommu->ctx[KGSL_IOMMU_CONTEXT_SECURE]; /* * set the fault bits and stuff before any printks so that if fault * handler runs then it will know it's dealing with a pagefault. * Read the global current timestamp because we could be in middle of * RB switch and hence the cur RB may not be reliable but global * one will always be reliable */ kgsl_sharedmem_readl(&device->memstore, &curr_context_id, KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context)); context = kgsl_context_get(device, curr_context_id); write = (flags & IOMMU_FAULT_WRITE) ? 1 : 0; if (flags & IOMMU_FAULT_TRANSLATION) fault_type = "translation"; Loading @@ -747,12 +752,17 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain, else if (flags & IOMMU_FAULT_TRANSACTION_STALLED) fault_type = "transaction stalled"; if (context != NULL) { /* save pagefault timestamp for GFT */ set_bit(KGSL_CONTEXT_PRIV_PAGEFAULT, &context->priv); pid = context->proc_priv->pid; ptbase = KGSL_IOMMU_GET_CTX_REG_Q(ctx, TTBR0); private = kgsl_iommu_get_process(ptbase); if (private) { pid = private->pid; comm = private->comm; } if (pt->name == KGSL_MMU_SECURE_PT) ctx = &iommu->ctx[KGSL_IOMMU_CONTEXT_SECURE]; ctx->fault = 1; if (test_bit(KGSL_FT_PAGEFAULT_GPUHALT_ENABLE, Loading @@ -767,9 +777,7 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain, mutex_unlock(&device->mutex); } ptbase = KGSL_IOMMU_GET_CTX_REG_Q(ctx, TTBR0); contextidr = KGSL_IOMMU_GET_CTX_REG(ctx, CONTEXTIDR); ptname = MMU_FEATURE(mmu, KGSL_MMU_GLOBAL_PAGETABLE) ? KGSL_MMU_GLOBAL_PT : pid; /* Loading @@ -778,43 +786,19 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain, * search and delays the trace unnecessarily. */ trace_kgsl_mmu_pagefault(ctx->kgsldev, addr, ptname, context != NULL ? context->proc_priv->comm : "unknown", write ? "write" : "read"); ptname, comm, write ? "write" : "read"); if (test_bit(KGSL_FT_PAGEFAULT_LOG_ONE_PER_PAGE, &adreno_dev->ft_pf_policy)) no_page_fault_log = kgsl_mmu_log_fault_addr(mmu, ptbase, addr); if (!no_page_fault_log && __ratelimit(&_rs)) { const char *api_str; if (context != NULL) { struct adreno_context *drawctxt = ADRENO_CONTEXT(context); api_str = get_api_type_str(drawctxt->type); } else api_str = "UNKNOWN"; dev_crit(ctx->kgsldev->dev, "GPU PAGE FAULT: addr = %lX pid= %d name=%s\n", addr, ptname, context != NULL ? context->proc_priv->comm : "unknown"); if (context != NULL) { proc_ptbase = kgsl_mmu_pagetable_get_ttbr0( context->proc_priv->pagetable); if (ptbase != proc_ptbase) ptname, comm); dev_crit(ctx->kgsldev->dev, "Pagetable address mismatch: HW address is 0x%llx but SW expected 0x%llx\n", ptbase, proc_ptbase); } dev_crit(ctx->kgsldev->dev, "context=%s ctx_type=%s TTBR0=0x%llx CIDR=0x%x (%s %s fault)\n", ctx->name, api_str, ptbase, contextidr, "context=%s TTBR0=0x%llx CIDR=0x%x (%s %s fault)\n", ctx->name, ptbase, contextidr, write ? "write" : "read", fault_type); if (gpudev->iommu_fault_block) { Loading @@ -834,7 +818,7 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain, dev_err(ctx->kgsldev->dev, "---- nearby memory ----\n"); _find_mem_entries(mmu, addr, &prev, &next, context); _find_mem_entries(mmu, addr, &prev, &next, private); if (prev.gpuaddr) _print_entry(ctx->kgsldev, &prev); else Loading Loading @@ -877,7 +861,8 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain, adreno_dispatcher_schedule(device); } kgsl_context_put(context); kgsl_process_private_put(private); return ret; } Loading