Loading drivers/gpu/msm/adreno.c +20 −3 Original line number Diff line number Diff line Loading @@ -2079,15 +2079,32 @@ static ssize_t _ft_pagefault_policy_store(struct device *dev, const char *buf, size_t count) { struct adreno_device *adreno_dev = _get_adreno_dev(dev); int ret; int ret = 0; unsigned int policy = 0; if (adreno_dev == NULL) return 0; mutex_lock(&adreno_dev->dev.mutex); ret = kgsl_sysfs_store(buf, count, &adreno_dev->ft_pf_policy); /* MMU option changed call function to reset MMU options */ if (count != kgsl_sysfs_store(buf, count, &policy)) ret = -EINVAL; if (!ret) { policy &= (KGSL_FT_PAGEFAULT_INT_ENABLE | KGSL_FT_PAGEFAULT_GPUHALT_ENABLE | KGSL_FT_PAGEFAULT_LOG_ONE_PER_PAGE | KGSL_FT_PAGEFAULT_LOG_ONE_PER_INT); ret = kgsl_mmu_set_pagefault_policy(&(adreno_dev->dev.mmu), adreno_dev->ft_pf_policy); if (!ret) adreno_dev->ft_pf_policy = policy; } mutex_unlock(&adreno_dev->dev.mutex); return ret; if (!ret) return count; else return 0; } /** Loading drivers/gpu/msm/kgsl_iommu.c +67 −0 Original line number Diff line number Diff line Loading @@ -2039,6 +2039,72 @@ static int kgsl_iommu_get_num_iommu_units(struct kgsl_mmu *mmu) return iommu->unit_count; } /* * kgsl_iommu_set_pf_policy() - Set the pagefault policy for IOMMU * @mmu: Pointer to mmu structure * @pf_policy: The pagefault polict to set * * Check if the new policy indicated by pf_policy is same as current * policy, if same then return else set the policy */ static int kgsl_iommu_set_pf_policy(struct kgsl_mmu *mmu, unsigned int pf_policy) { int i, j; struct kgsl_iommu *iommu = mmu->priv; struct adreno_device *adreno_dev = ADRENO_DEVICE(mmu->device); int ret = 0; unsigned int sctlr_val; if ((adreno_dev->ft_pf_policy & KGSL_FT_PAGEFAULT_GPUHALT_ENABLE) == (pf_policy & KGSL_FT_PAGEFAULT_GPUHALT_ENABLE)) return ret; if (msm_soc_version_supports_iommu_v0()) return ret; ret = kgsl_iommu_enable_clk(mmu, KGSL_IOMMU_CONTEXT_USER); if (ret) { KGSL_DRV_ERR(mmu->device, "Failed to enable iommu clocks\n"); return ret; } ret = kgsl_iommu_enable_clk(mmu, KGSL_IOMMU_CONTEXT_PRIV); if (ret) { KGSL_DRV_ERR(mmu->device, "Failed to enable iommu clocks\n"); kgsl_iommu_disable_clk_on_ts(mmu, 0, false); return ret; } /* Need to idle device before changing options */ ret = mmu->device->ftbl->idle(mmu->device); if (ret) { kgsl_iommu_disable_clk_on_ts(mmu, 0, false); return ret; } for (i = 0; i < iommu->unit_count; i++) { struct kgsl_iommu_unit *iommu_unit = &iommu->iommu_units[i]; for (j = 0; j < iommu_unit->dev_count; j++) { sctlr_val = KGSL_IOMMU_GET_CTX_REG(iommu, iommu_unit, iommu_unit->dev[j].ctx_id, SCTLR); if (pf_policy & KGSL_FT_PAGEFAULT_GPUHALT_ENABLE) sctlr_val &= ~(0x1 << KGSL_IOMMU_SCTLR_HUPCF_SHIFT); else sctlr_val |= (0x1 << KGSL_IOMMU_SCTLR_HUPCF_SHIFT); KGSL_IOMMU_SET_CTX_REG(iommu, iommu_unit, iommu_unit->dev[j].ctx_id, SCTLR, sctlr_val); } } kgsl_iommu_disable_clk_on_ts(mmu, 0, false); return ret; } struct kgsl_mmu_ops iommu_ops = { .mmu_init = kgsl_iommu_init, .mmu_close = kgsl_iommu_close, Loading @@ -2064,6 +2130,7 @@ struct kgsl_mmu_ops iommu_ops = { .mmu_cleanup_pt = NULL, .mmu_sync_lock = kgsl_iommu_sync_lock, .mmu_sync_unlock = kgsl_iommu_sync_unlock, .mmu_set_pf_policy = kgsl_iommu_set_pf_policy, }; struct kgsl_mmu_pt_ops iommu_pt_ops = { Loading drivers/gpu/msm/kgsl_mmu.h +11 −1 Original line number Diff line number Diff line /* Copyright (c) 2002,2007-2013, The Linux Foundation. All rights reserved. /* Copyright (c) 2002,2007-2014, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -128,6 +128,7 @@ struct kgsl_mmu_ops { unsigned int (*mmu_sync_unlock) (struct kgsl_mmu *mmu, unsigned int *cmds); int (*mmu_hw_halt_supported)(struct kgsl_mmu *mmu, int iommu_unit_num); int (*mmu_set_pf_policy)(struct kgsl_mmu *mmu, unsigned int pf_policy); }; struct kgsl_mmu_pt_ops { Loading Loading @@ -415,4 +416,13 @@ static inline int kgsl_mmu_sync_unlock(struct kgsl_mmu *mmu, return 0; } static inline int kgsl_mmu_set_pagefault_policy(struct kgsl_mmu *mmu, unsigned int pf_policy) { if (mmu->mmu_ops && mmu->mmu_ops->mmu_set_pf_policy) return mmu->mmu_ops->mmu_set_pf_policy(mmu, pf_policy); else return 0; } #endif /* __KGSL_MMU_H */ Loading
drivers/gpu/msm/adreno.c +20 −3 Original line number Diff line number Diff line Loading @@ -2079,15 +2079,32 @@ static ssize_t _ft_pagefault_policy_store(struct device *dev, const char *buf, size_t count) { struct adreno_device *adreno_dev = _get_adreno_dev(dev); int ret; int ret = 0; unsigned int policy = 0; if (adreno_dev == NULL) return 0; mutex_lock(&adreno_dev->dev.mutex); ret = kgsl_sysfs_store(buf, count, &adreno_dev->ft_pf_policy); /* MMU option changed call function to reset MMU options */ if (count != kgsl_sysfs_store(buf, count, &policy)) ret = -EINVAL; if (!ret) { policy &= (KGSL_FT_PAGEFAULT_INT_ENABLE | KGSL_FT_PAGEFAULT_GPUHALT_ENABLE | KGSL_FT_PAGEFAULT_LOG_ONE_PER_PAGE | KGSL_FT_PAGEFAULT_LOG_ONE_PER_INT); ret = kgsl_mmu_set_pagefault_policy(&(adreno_dev->dev.mmu), adreno_dev->ft_pf_policy); if (!ret) adreno_dev->ft_pf_policy = policy; } mutex_unlock(&adreno_dev->dev.mutex); return ret; if (!ret) return count; else return 0; } /** Loading
drivers/gpu/msm/kgsl_iommu.c +67 −0 Original line number Diff line number Diff line Loading @@ -2039,6 +2039,72 @@ static int kgsl_iommu_get_num_iommu_units(struct kgsl_mmu *mmu) return iommu->unit_count; } /* * kgsl_iommu_set_pf_policy() - Set the pagefault policy for IOMMU * @mmu: Pointer to mmu structure * @pf_policy: The pagefault polict to set * * Check if the new policy indicated by pf_policy is same as current * policy, if same then return else set the policy */ static int kgsl_iommu_set_pf_policy(struct kgsl_mmu *mmu, unsigned int pf_policy) { int i, j; struct kgsl_iommu *iommu = mmu->priv; struct adreno_device *adreno_dev = ADRENO_DEVICE(mmu->device); int ret = 0; unsigned int sctlr_val; if ((adreno_dev->ft_pf_policy & KGSL_FT_PAGEFAULT_GPUHALT_ENABLE) == (pf_policy & KGSL_FT_PAGEFAULT_GPUHALT_ENABLE)) return ret; if (msm_soc_version_supports_iommu_v0()) return ret; ret = kgsl_iommu_enable_clk(mmu, KGSL_IOMMU_CONTEXT_USER); if (ret) { KGSL_DRV_ERR(mmu->device, "Failed to enable iommu clocks\n"); return ret; } ret = kgsl_iommu_enable_clk(mmu, KGSL_IOMMU_CONTEXT_PRIV); if (ret) { KGSL_DRV_ERR(mmu->device, "Failed to enable iommu clocks\n"); kgsl_iommu_disable_clk_on_ts(mmu, 0, false); return ret; } /* Need to idle device before changing options */ ret = mmu->device->ftbl->idle(mmu->device); if (ret) { kgsl_iommu_disable_clk_on_ts(mmu, 0, false); return ret; } for (i = 0; i < iommu->unit_count; i++) { struct kgsl_iommu_unit *iommu_unit = &iommu->iommu_units[i]; for (j = 0; j < iommu_unit->dev_count; j++) { sctlr_val = KGSL_IOMMU_GET_CTX_REG(iommu, iommu_unit, iommu_unit->dev[j].ctx_id, SCTLR); if (pf_policy & KGSL_FT_PAGEFAULT_GPUHALT_ENABLE) sctlr_val &= ~(0x1 << KGSL_IOMMU_SCTLR_HUPCF_SHIFT); else sctlr_val |= (0x1 << KGSL_IOMMU_SCTLR_HUPCF_SHIFT); KGSL_IOMMU_SET_CTX_REG(iommu, iommu_unit, iommu_unit->dev[j].ctx_id, SCTLR, sctlr_val); } } kgsl_iommu_disable_clk_on_ts(mmu, 0, false); return ret; } struct kgsl_mmu_ops iommu_ops = { .mmu_init = kgsl_iommu_init, .mmu_close = kgsl_iommu_close, Loading @@ -2064,6 +2130,7 @@ struct kgsl_mmu_ops iommu_ops = { .mmu_cleanup_pt = NULL, .mmu_sync_lock = kgsl_iommu_sync_lock, .mmu_sync_unlock = kgsl_iommu_sync_unlock, .mmu_set_pf_policy = kgsl_iommu_set_pf_policy, }; struct kgsl_mmu_pt_ops iommu_pt_ops = { Loading
drivers/gpu/msm/kgsl_mmu.h +11 −1 Original line number Diff line number Diff line /* Copyright (c) 2002,2007-2013, The Linux Foundation. All rights reserved. /* Copyright (c) 2002,2007-2014, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -128,6 +128,7 @@ struct kgsl_mmu_ops { unsigned int (*mmu_sync_unlock) (struct kgsl_mmu *mmu, unsigned int *cmds); int (*mmu_hw_halt_supported)(struct kgsl_mmu *mmu, int iommu_unit_num); int (*mmu_set_pf_policy)(struct kgsl_mmu *mmu, unsigned int pf_policy); }; struct kgsl_mmu_pt_ops { Loading Loading @@ -415,4 +416,13 @@ static inline int kgsl_mmu_sync_unlock(struct kgsl_mmu *mmu, return 0; } static inline int kgsl_mmu_set_pagefault_policy(struct kgsl_mmu *mmu, unsigned int pf_policy) { if (mmu->mmu_ops && mmu->mmu_ops->mmu_set_pf_policy) return mmu->mmu_ops->mmu_set_pf_policy(mmu, pf_policy); else return 0; } #endif /* __KGSL_MMU_H */