diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c index 6391409eda8d..10fc07198ee3 100644 --- a/drivers/gpu/msm/kgsl_iommu.c +++ b/drivers/gpu/msm/kgsl_iommu.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2011-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2020, The Linux Foundation. All rights reserved. */ #include @@ -93,6 +93,29 @@ static void kgsl_iommu_map_globals(struct kgsl_mmu *mmu, kgsl_mmu_map(pagetable, &md->memdesc); } +static void kgsl_iommu_map_global(struct kgsl_mmu *mmu, + struct kgsl_memdesc *memdesc) +{ + struct kgsl_iommu *iommu = _IOMMU_PRIV(mmu); + + /* + * If the global pagetable hasn't been created yet, do nothing. We'll + * get them all in one big swoop at create time + */ + if (!mmu->defaultpagetable) + return; + + /* + * Warn if a global is added after first per-process pagetables have + * been created since we do not go back and retroactively add the + * globals to existing pages + */ + WARN_ON(iommu->ppt_active); + + /* Map the buffer in the default pagetable */ + kgsl_mmu_map(mmu->defaultpagetable, memdesc); +} + static u64 kgsl_iommu_get_global_base(struct kgsl_mmu *mmu) { return KGSL_IOMMU_GLOBAL_MEM_BASE(mmu); @@ -1125,6 +1148,8 @@ static int _init_per_process_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt) goto done; } + iommu->ppt_active = true; + kgsl_iommu_map_globals(mmu, pt); done: @@ -2400,6 +2425,7 @@ struct kgsl_mmu_ops kgsl_iommu_ops = { .mmu_init_pt = kgsl_iommu_init_pt, .mmu_getpagetable = kgsl_iommu_getpagetable, .mmu_get_global_base = kgsl_iommu_get_global_base, + .mmu_map_global = kgsl_iommu_map_global, .probe = kgsl_iommu_probe, }; diff --git a/drivers/gpu/msm/kgsl_iommu.h b/drivers/gpu/msm/kgsl_iommu.h index dba254397a66..64a0a8c85098 100644 --- a/drivers/gpu/msm/kgsl_iommu.h +++ b/drivers/gpu/msm/kgsl_iommu.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. */ #ifndef __KGSL_IOMMU_H #define __KGSL_IOMMU_H @@ -124,6 +124,12 @@ struct kgsl_iommu { struct kgsl_memdesc *smmu_info; /** @pdev: Pointer to the platform device for the IOMMU device */ struct platform_device *pdev; + /** + * @ppt_active: Set when the first per process pagetable is created. + * This is used to warn when global buffers are created that might not + * be mapped in all contexts + */ + bool ppt_active; }; /* diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c index e3dcdb629d6c..e7411896f17c 100644 --- a/drivers/gpu/msm/kgsl_mmu.c +++ b/drivers/gpu/msm/kgsl_mmu.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2002,2007-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2002,2007-2020, The Linux Foundation. All rights reserved. */ #include @@ -537,6 +537,15 @@ u64 kgsl_mmu_get_global_base(struct kgsl_device *device) return 0; } +void kgsl_mmu_map_global(struct kgsl_device *device, + struct kgsl_memdesc *memdesc) +{ + struct kgsl_mmu *mmu = &(device->mmu); + + if (MMU_OP_VALID(mmu, mmu_map_global)) + mmu->mmu_ops->mmu_map_global(mmu, memdesc); +} + void kgsl_mmu_close(struct kgsl_device *device) { struct kgsl_mmu *mmu = &(device->mmu); diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h index 952dbb70b3b4..cdef06d1741d 100644 --- a/drivers/gpu/msm/kgsl_mmu.h +++ b/drivers/gpu/msm/kgsl_mmu.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2002,2007-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2002,2007-2020, The Linux Foundation. All rights reserved. */ #ifndef __KGSL_MMU_H #define __KGSL_MMU_H @@ -71,6 +71,8 @@ struct kgsl_mmu_ops { struct kgsl_pagetable * (*mmu_getpagetable)(struct kgsl_mmu *mmu, unsigned long name); u64 (*mmu_get_global_base)(struct kgsl_mmu *mmu); + void (*mmu_map_global)(struct kgsl_mmu *mmu, + struct kgsl_memdesc *memdesc); }; struct kgsl_mmu_pt_ops { @@ -344,4 +346,14 @@ kgsl_mmu_pagetable_get_contextidr(struct kgsl_pagetable *pagetable) */ u64 kgsl_mmu_get_global_base(struct kgsl_device *device); +/** + * kgsl_mmu_map_global - Map a memdesc as a global buffer + * @device: A KGSL GPU device handle + * @memdesc: Pointer to a GPU memory descriptor + * + * Map a buffer as globally accessible in all pagetable contexts + */ +void kgsl_mmu_map_global(struct kgsl_device *device, + struct kgsl_memdesc *memdesc); + #endif /* __KGSL_MMU_H */ diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c index ba33934c94d2..95d1a990bd61 100644 --- a/drivers/gpu/msm/kgsl_sharedmem.c +++ b/drivers/gpu/msm/kgsl_sharedmem.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2002,2007-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2002,2007-2020, The Linux Foundation. All rights reserved. */ #include @@ -1325,6 +1325,8 @@ struct kgsl_memdesc *kgsl_allocate_global_fixed(struct kgsl_device *device, */ list_add_tail(&md->node, &device->globals); + kgsl_mmu_map_global(device, &md->memdesc); + return &md->memdesc; } @@ -1374,6 +1376,8 @@ struct kgsl_memdesc *kgsl_allocate_global(struct kgsl_device *device, */ list_add_tail(&md->node, &device->globals); + kgsl_mmu_map_global(device, &md->memdesc); + return &md->memdesc; }