Loading drivers/gpu/msm/kgsl_iommu.c +34 −7 Original line number Diff line number Diff line Loading @@ -68,6 +68,11 @@ static struct kgsl_iommu_register_list kgsl_iommuv1_reg[KGSL_IOMMU_REG_MAX] = { static struct iommu_access_ops *iommu_access_ops; static int kgsl_iommu_default_setstate(struct kgsl_mmu *mmu, uint32_t flags); static phys_addr_t kgsl_iommu_get_current_ptbase(struct kgsl_mmu *mmu); static void _iommu_lock(struct kgsl_iommu const *iommu) { if (iommu_access_ops && iommu_access_ops->iommu_lock_acquire) Loading Loading @@ -1681,9 +1686,11 @@ kgsl_iommu_unmap(struct kgsl_pagetable *pt, struct kgsl_memdesc *memdesc, unsigned int *tlb_flags) { int ret; int ret = 0, lock_taken = 0; unsigned int range = memdesc->size; struct kgsl_iommu_pt *iommu_pt = pt->priv; struct kgsl_device *device = pt->mmu->device; struct kgsl_iommu *iommu = pt->mmu->priv; /* All GPU addresses as assigned are page aligned, but some functions purturb the gpuaddr with an offset, so apply the Loading @@ -1698,18 +1705,38 @@ kgsl_iommu_unmap(struct kgsl_pagetable *pt, range += PAGE_SIZE; ret = iommu_unmap_range(iommu_pt->domain, gpuaddr, range); if (ret) if (ret) { KGSL_CORE_ERR("iommu_unmap_range(%p, %x, %d) failed " "with err: %d\n", iommu_pt->domain, gpuaddr, range, ret); return ret; } /* * Flushing only required if per process pagetables are used. With * global case, flushing will happen inside iommu_map function * Check to see if the current thread already holds the device mutex. * If it does not, then take the device mutex which is required for * flushing the tlb */ if (!ret && kgsl_mmu_is_perprocess(pt->mmu)) *tlb_flags = UINT_MAX; return 0; if (!mutex_is_locked(&device->mutex) || device->mutex.owner != current) { mutex_lock(&device->mutex); lock_taken = 1; } /* * Flush the tlb only if the iommu device is attached and the pagetable * hasn't been switched yet */ if (kgsl_mmu_is_perprocess(pt->mmu) && iommu->iommu_units[0].dev[KGSL_IOMMU_CONTEXT_USER].attached && kgsl_iommu_pt_equal(pt->mmu, pt, kgsl_iommu_get_current_ptbase(pt->mmu))) kgsl_iommu_default_setstate(pt->mmu, KGSL_MMUFLAGS_TLBFLUSH); if (lock_taken) mutex_unlock(&device->mutex); return ret; } static int Loading Loading
drivers/gpu/msm/kgsl_iommu.c +34 −7 Original line number Diff line number Diff line Loading @@ -68,6 +68,11 @@ static struct kgsl_iommu_register_list kgsl_iommuv1_reg[KGSL_IOMMU_REG_MAX] = { static struct iommu_access_ops *iommu_access_ops; static int kgsl_iommu_default_setstate(struct kgsl_mmu *mmu, uint32_t flags); static phys_addr_t kgsl_iommu_get_current_ptbase(struct kgsl_mmu *mmu); static void _iommu_lock(struct kgsl_iommu const *iommu) { if (iommu_access_ops && iommu_access_ops->iommu_lock_acquire) Loading Loading @@ -1681,9 +1686,11 @@ kgsl_iommu_unmap(struct kgsl_pagetable *pt, struct kgsl_memdesc *memdesc, unsigned int *tlb_flags) { int ret; int ret = 0, lock_taken = 0; unsigned int range = memdesc->size; struct kgsl_iommu_pt *iommu_pt = pt->priv; struct kgsl_device *device = pt->mmu->device; struct kgsl_iommu *iommu = pt->mmu->priv; /* All GPU addresses as assigned are page aligned, but some functions purturb the gpuaddr with an offset, so apply the Loading @@ -1698,18 +1705,38 @@ kgsl_iommu_unmap(struct kgsl_pagetable *pt, range += PAGE_SIZE; ret = iommu_unmap_range(iommu_pt->domain, gpuaddr, range); if (ret) if (ret) { KGSL_CORE_ERR("iommu_unmap_range(%p, %x, %d) failed " "with err: %d\n", iommu_pt->domain, gpuaddr, range, ret); return ret; } /* * Flushing only required if per process pagetables are used. With * global case, flushing will happen inside iommu_map function * Check to see if the current thread already holds the device mutex. * If it does not, then take the device mutex which is required for * flushing the tlb */ if (!ret && kgsl_mmu_is_perprocess(pt->mmu)) *tlb_flags = UINT_MAX; return 0; if (!mutex_is_locked(&device->mutex) || device->mutex.owner != current) { mutex_lock(&device->mutex); lock_taken = 1; } /* * Flush the tlb only if the iommu device is attached and the pagetable * hasn't been switched yet */ if (kgsl_mmu_is_perprocess(pt->mmu) && iommu->iommu_units[0].dev[KGSL_IOMMU_CONTEXT_USER].attached && kgsl_iommu_pt_equal(pt->mmu, pt, kgsl_iommu_get_current_ptbase(pt->mmu))) kgsl_iommu_default_setstate(pt->mmu, KGSL_MMUFLAGS_TLBFLUSH); if (lock_taken) mutex_unlock(&device->mutex); return ret; } static int Loading