static int kgsl_iommu_close(struct kgsl_mmu *mmu) { struct kgsl_iommu *iommu = mmu->priv; int i; for (i = 0; i < iommu->unit_count; i++) { struct kgsl_pagetable *pagetable = (mmu->priv_bank_table ? mmu->priv_bank_table : mmu->defaultpagetable); if (iommu->iommu_units[i].reg_map.gpuaddr) kgsl_mmu_unmap(pagetable, &(iommu->iommu_units[i].reg_map)); if (iommu->iommu_units[i].reg_map.hostptr) iounmap(iommu->iommu_units[i].reg_map.hostptr); kgsl_sg_free(iommu->iommu_units[i].reg_map.sg, iommu->iommu_units[i].reg_map.sglen); } if (mmu->priv_bank_table) kgsl_mmu_putpagetable(mmu->priv_bank_table); if (mmu->defaultpagetable) kgsl_mmu_putpagetable(mmu->defaultpagetable); kfree(iommu->asids); kfree(iommu); return 0; }
/* * kgsl_iommu_setup_defaultpagetable - Setup the initial defualtpagetable * for iommu. This function is only called once during first start, successive * start do not call this funciton. * @mmu - Pointer to mmu structure * * Create the initial defaultpagetable and setup the iommu mappings to it * Return - 0 on success else error code */ static int kgsl_iommu_setup_defaultpagetable(struct kgsl_mmu *mmu) { int status = 0; int i = 0; struct kgsl_iommu *iommu = mmu->priv; struct kgsl_pagetable *pagetable = NULL; /* If chip is not 8960 then we use the 2nd context bank for pagetable * switching on the 3D side for which a separate table is allocated */ if (!cpu_is_msm8960() && msm_soc_version_supports_iommu_v1()) { mmu->priv_bank_table = kgsl_mmu_getpagetable(KGSL_MMU_PRIV_BANK_TABLE_NAME); if (mmu->priv_bank_table == NULL) { status = -ENOMEM; goto err; } } mmu->defaultpagetable = kgsl_mmu_getpagetable(KGSL_MMU_GLOBAL_PT); /* Return error if the default pagetable doesn't exist */ if (mmu->defaultpagetable == NULL) { status = -ENOMEM; goto err; } pagetable = mmu->priv_bank_table ? mmu->priv_bank_table : mmu->defaultpagetable; /* Map the IOMMU regsiters to only defaultpagetable */ if (msm_soc_version_supports_iommu_v1()) { for (i = 0; i < iommu->unit_count; i++) { iommu->iommu_units[i].reg_map.priv |= KGSL_MEMFLAGS_GLOBAL; status = kgsl_mmu_map(pagetable, &(iommu->iommu_units[i].reg_map), GSL_PT_PAGE_RV | GSL_PT_PAGE_WV); if (status) { iommu->iommu_units[i].reg_map.priv &= ~KGSL_MEMFLAGS_GLOBAL; goto err; } } } return status; err: for (i--; i >= 0; i--) { kgsl_mmu_unmap(pagetable, &(iommu->iommu_units[i].reg_map)); iommu->iommu_units[i].reg_map.priv &= ~KGSL_MEMFLAGS_GLOBAL; } if (mmu->priv_bank_table) { kgsl_mmu_putpagetable(mmu->priv_bank_table); mmu->priv_bank_table = NULL; } if (mmu->defaultpagetable) { kgsl_mmu_putpagetable(mmu->defaultpagetable); mmu->defaultpagetable = NULL; } return status; }
static int kgsl_iommu_setup_defaultpagetable(struct kgsl_mmu *mmu) { int status = 0; int i = 0; struct kgsl_iommu *iommu = mmu->priv; struct kgsl_iommu_pt *iommu_pt; struct kgsl_pagetable *pagetable = NULL; if (!cpu_is_msm8960()) { mmu->priv_bank_table = kgsl_mmu_getpagetable(KGSL_MMU_PRIV_BANK_TABLE_NAME); if (mmu->priv_bank_table == NULL) { status = -ENOMEM; goto err; } iommu_pt = mmu->priv_bank_table->priv; } mmu->defaultpagetable = kgsl_mmu_getpagetable(KGSL_MMU_GLOBAL_PT); if (mmu->defaultpagetable == NULL) { status = -ENOMEM; goto err; } pagetable = mmu->priv_bank_table ? mmu->priv_bank_table : mmu->defaultpagetable; for (i = 0; i < iommu->unit_count; i++) { iommu->iommu_units[i].reg_map.priv |= KGSL_MEMFLAGS_GLOBAL; status = kgsl_mmu_map(pagetable, &(iommu->iommu_units[i].reg_map), GSL_PT_PAGE_RV | GSL_PT_PAGE_WV); if (status) { iommu->iommu_units[i].reg_map.priv &= ~KGSL_MEMFLAGS_GLOBAL; goto err; } } return status; err: for (i--; i >= 0; i--) { kgsl_mmu_unmap(pagetable, &(iommu->iommu_units[i].reg_map)); iommu->iommu_units[i].reg_map.priv &= ~KGSL_MEMFLAGS_GLOBAL; } if (mmu->priv_bank_table) { kgsl_mmu_putpagetable(mmu->priv_bank_table); mmu->priv_bank_table = NULL; } if (mmu->defaultpagetable) { kgsl_mmu_putpagetable(mmu->defaultpagetable); mmu->defaultpagetable = NULL; } return status; }
static int kgsl_iommu_close(struct kgsl_mmu *mmu) { if (mmu->defaultpagetable) kgsl_mmu_putpagetable(mmu->defaultpagetable); return 0; }
static int kgsl_iommu_close(struct kgsl_device *device) { struct kgsl_mmu *mmu = &device->mmu; if (mmu->defaultpagetable) kgsl_mmu_putpagetable(mmu->defaultpagetable); return 0; }
/* * kgsl_iommu_setup_defaultpagetable - Setup the initial defualtpagetable * for iommu. This function is only called once during first start, successive * start do not call this funciton. * @mmu - Pointer to mmu structure * * Create the initial defaultpagetable and setup the iommu mappings to it * Return - 0 on success else error code */ static int kgsl_iommu_setup_defaultpagetable(struct kgsl_mmu *mmu) { int status = 0; int i = 0; struct kgsl_iommu *iommu = mmu->priv; struct kgsl_iommu_pt *iommu_pt; mmu->defaultpagetable = kgsl_mmu_getpagetable(KGSL_MMU_GLOBAL_PT); /* Return error if the default pagetable doesn't exist */ if (mmu->defaultpagetable == NULL) { status = -ENOMEM; goto err; } /* Map the IOMMU regsiters to only defaultpagetable */ for (i = 0; i < iommu->unit_count; i++) { iommu->iommu_units[i].reg_map.priv |= KGSL_MEMFLAGS_GLOBAL; status = kgsl_mmu_map(mmu->defaultpagetable, &(iommu->iommu_units[i].reg_map), GSL_PT_PAGE_RV | GSL_PT_PAGE_WV); if (status) { iommu->iommu_units[i].reg_map.priv &= ~KGSL_MEMFLAGS_GLOBAL; goto err; } } /* * The dafault pagetable always has asid 0 assigned by the iommu driver * and asid 1 is assigned to the private context. */ iommu_pt = mmu->defaultpagetable->priv; iommu_pt->asid = 0; set_bit(0, iommu->asids); set_bit(1, iommu->asids); return status; err: for (i--; i >= 0; i--) { kgsl_mmu_unmap(mmu->defaultpagetable, &(iommu->iommu_units[i].reg_map)); iommu->iommu_units[i].reg_map.priv &= ~KGSL_MEMFLAGS_GLOBAL; } if (mmu->defaultpagetable) { kgsl_mmu_putpagetable(mmu->defaultpagetable); mmu->defaultpagetable = NULL; } return status; }
/* * kgsl_iommu_setup_defaultpagetable - Setup the initial defualtpagetable * for iommu. This function is only called once during first start, successive * start do not call this funciton. * @mmu - Pointer to mmu structure * * Create the initial defaultpagetable and setup the iommu mappings to it * Return - 0 on success else error code */ static int kgsl_iommu_setup_defaultpagetable(struct kgsl_mmu *mmu) { int status = 0; int i = 0; struct kgsl_iommu *iommu = mmu->priv; struct kgsl_iommu_pt *iommu_pt; struct kgsl_pagetable *pagetable = NULL; /* If chip is not 8960 then we use the 2nd context bank for pagetable * switching on the 3D side for which a separate table is allocated */ if (!cpu_is_msm8960()) { mmu->priv_bank_table = kgsl_mmu_getpagetable(KGSL_MMU_PRIV_BANK_TABLE_NAME); if (mmu->priv_bank_table == NULL) { status = -ENOMEM; goto err; } iommu_pt = mmu->priv_bank_table->priv; iommu_pt->asid = 1; } mmu->defaultpagetable = kgsl_mmu_getpagetable(KGSL_MMU_GLOBAL_PT); /* Return error if the default pagetable doesn't exist */ if (mmu->defaultpagetable == NULL) { status = -ENOMEM; goto err; } pagetable = mmu->priv_bank_table ? mmu->priv_bank_table : mmu->defaultpagetable; /* Map the IOMMU regsiters to only defaultpagetable */ for (i = 0; i < iommu->unit_count; i++) { iommu->iommu_units[i].reg_map.priv |= KGSL_MEMFLAGS_GLOBAL; status = kgsl_mmu_map(pagetable, &(iommu->iommu_units[i].reg_map), GSL_PT_PAGE_RV | GSL_PT_PAGE_WV); if (status) { iommu->iommu_units[i].reg_map.priv &= ~KGSL_MEMFLAGS_GLOBAL; goto err; } } /* * The dafault pagetable always has asid 0 assigned by the iommu driver * and asid 1 is assigned to the private context. */ iommu_pt = mmu->defaultpagetable->priv; iommu_pt->asid = 0; set_bit(0, iommu->asids); set_bit(1, iommu->asids); return status; err: for (i--; i >= 0; i--) { kgsl_mmu_unmap(pagetable, &(iommu->iommu_units[i].reg_map)); iommu->iommu_units[i].reg_map.priv &= ~KGSL_MEMFLAGS_GLOBAL; } if (mmu->priv_bank_table) { kgsl_mmu_putpagetable(mmu->priv_bank_table); mmu->priv_bank_table = NULL; } if (mmu->defaultpagetable) { kgsl_mmu_putpagetable(mmu->defaultpagetable); mmu->defaultpagetable = NULL; } return status; }