Loading drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c +2 −2 Original line number Diff line number Diff line Loading @@ -120,8 +120,8 @@ nvkm_device_tegra_probe_iommu(struct nvkm_device_tegra *tdev) mutex_init(&tdev->iommu.mutex); if (device_iommu_mapped(dev)) { tdev->iommu.domain = iommu_domain_alloc(&platform_bus_type); if (!tdev->iommu.domain) tdev->iommu.domain = iommu_paging_domain_alloc(dev); if (IS_ERR(tdev->iommu.domain)) goto error; /* Loading drivers/iommu/amd/amd_iommu.h +7 −1 Original line number Diff line number Diff line Loading @@ -46,6 +46,7 @@ extern int amd_iommu_gpt_level; extern unsigned long amd_iommu_pgsize_bitmap; /* Protection domain ops */ void amd_iommu_init_identity_domain(void); struct protection_domain *protection_domain_alloc(unsigned int type, int nid); void protection_domain_free(struct protection_domain *domain); struct iommu_domain *amd_iommu_domain_alloc_sva(struct device *dev, Loading Loading @@ -118,9 +119,14 @@ static inline bool check_feature2(u64 mask) return (amd_iommu_efr2 & mask); } static inline bool amd_iommu_v2_pgtbl_supported(void) { return (check_feature(FEATURE_GIOSUP) && check_feature(FEATURE_GT)); } static inline bool amd_iommu_gt_ppr_supported(void) { return (check_feature(FEATURE_GT) && return (amd_iommu_v2_pgtbl_supported() && check_feature(FEATURE_PPR) && check_feature(FEATURE_EPHSUP)); } Loading drivers/iommu/amd/init.c +10 −8 Original line number Diff line number Diff line Loading @@ -2070,14 +2070,6 @@ static int __init iommu_init_pci(struct amd_iommu *iommu) init_iommu_perf_ctr(iommu); if (amd_iommu_pgtable == AMD_IOMMU_V2) { if (!check_feature(FEATURE_GIOSUP) || !check_feature(FEATURE_GT)) { pr_warn("Cannot enable v2 page table for DMA-API. Fallback to v1.\n"); amd_iommu_pgtable = AMD_IOMMU_V1; } } if (is_rd890_iommu(iommu->dev)) { int i, j; Loading Loading @@ -2172,6 +2164,9 @@ static int __init amd_iommu_init_pci(void) struct amd_iommu_pci_seg *pci_seg; int ret; /* Init global identity domain before registering IOMMU */ amd_iommu_init_identity_domain(); for_each_iommu(iommu) { ret = iommu_init_pci(iommu); if (ret) { Loading Loading @@ -3087,6 +3082,13 @@ static int __init early_amd_iommu_init(void) FIELD_GET(FEATURE_GATS, amd_iommu_efr) == GUEST_PGTABLE_5_LEVEL) amd_iommu_gpt_level = PAGE_MODE_5_LEVEL; if (amd_iommu_pgtable == AMD_IOMMU_V2) { if (!amd_iommu_v2_pgtbl_supported()) { pr_warn("Cannot enable v2 page table for DMA-API. Fallback to v1.\n"); amd_iommu_pgtable = AMD_IOMMU_V1; } } /* Disable any previously enabled IOMMUs */ if (!is_kdump_kernel() || amd_iommu_disabled) disable_iommus(); Loading drivers/iommu/amd/iommu.c +98 −43 Original line number Diff line number Diff line Loading @@ -74,6 +74,9 @@ struct kmem_cache *amd_iommu_irq_cache; static void detach_device(struct device *dev); static int amd_iommu_attach_device(struct iommu_domain *dom, struct device *dev); static void set_dte_entry(struct amd_iommu *iommu, struct iommu_dev_data *dev_data); Loading Loading @@ -2263,44 +2266,42 @@ void protection_domain_free(struct protection_domain *domain) kfree(domain); } static void protection_domain_init(struct protection_domain *domain, int nid) { spin_lock_init(&domain->lock); INIT_LIST_HEAD(&domain->dev_list); INIT_LIST_HEAD(&domain->dev_data_list); domain->iop.pgtbl.cfg.amd.nid = nid; } struct protection_domain *protection_domain_alloc(unsigned int type, int nid) { struct io_pgtable_ops *pgtbl_ops; struct protection_domain *domain; int pgtable; domain = kzalloc(sizeof(*domain), GFP_KERNEL); if (!domain) return NULL; domain->id = domain_id_alloc(); if (!domain->id) goto err_free; if (!domain->id) { kfree(domain); return NULL; } spin_lock_init(&domain->lock); INIT_LIST_HEAD(&domain->dev_list); INIT_LIST_HEAD(&domain->dev_data_list); domain->iop.pgtbl.cfg.amd.nid = nid; protection_domain_init(domain, nid); switch (type) { /* No need to allocate io pgtable ops in passthrough mode */ case IOMMU_DOMAIN_IDENTITY: case IOMMU_DOMAIN_SVA: return domain; case IOMMU_DOMAIN_DMA: pgtable = amd_iommu_pgtable; break; /* * Force IOMMU v1 page table when allocating * domain for pass-through devices. */ case IOMMU_DOMAIN_UNMANAGED: pgtable = AMD_IOMMU_V1; break; default: goto err_id; } static int pdom_setup_pgtable(struct protection_domain *domain, unsigned int type, int pgtable) { struct io_pgtable_ops *pgtbl_ops; /* No need to allocate io pgtable ops in passthrough mode */ if (!(type & __IOMMU_DOMAIN_PAGING)) return 0; switch (pgtable) { case AMD_IOMMU_V1: domain->pd_mode = PD_MODE_V1; Loading @@ -2309,25 +2310,20 @@ struct protection_domain *protection_domain_alloc(unsigned int type, int nid) domain->pd_mode = PD_MODE_V2; break; default: goto err_id; return -EINVAL; } pgtbl_ops = alloc_io_pgtable_ops(pgtable, &domain->iop.pgtbl.cfg, domain); if (!pgtbl_ops) goto err_id; return -ENOMEM; return domain; err_id: domain_id_free(domain->id); err_free: kfree(domain); return NULL; return 0; } static inline u64 dma_max_address(void) static inline u64 dma_max_address(int pgtable) { if (amd_iommu_pgtable == AMD_IOMMU_V1) if (pgtable == AMD_IOMMU_V1) return ~0ULL; /* V2 with 4/5 level page table */ Loading @@ -2340,11 +2336,13 @@ static bool amd_iommu_hd_support(struct amd_iommu *iommu) } static struct iommu_domain *do_iommu_domain_alloc(unsigned int type, struct device *dev, u32 flags) struct device *dev, u32 flags, int pgtable) { bool dirty_tracking = flags & IOMMU_HWPT_ALLOC_DIRTY_TRACKING; struct protection_domain *domain; struct amd_iommu *iommu = NULL; int ret; if (dev) iommu = get_amd_iommu_from_dev(dev); Loading @@ -2356,16 +2354,20 @@ static struct iommu_domain *do_iommu_domain_alloc(unsigned int type, if (amd_iommu_snp_en && (type == IOMMU_DOMAIN_IDENTITY)) return ERR_PTR(-EINVAL); if (dirty_tracking && !amd_iommu_hd_support(iommu)) return ERR_PTR(-EOPNOTSUPP); domain = protection_domain_alloc(type, dev ? dev_to_node(dev) : NUMA_NO_NODE); if (!domain) return ERR_PTR(-ENOMEM); ret = pdom_setup_pgtable(domain, type, pgtable); if (ret) { domain_id_free(domain->id); kfree(domain); return ERR_PTR(ret); } domain->domain.geometry.aperture_start = 0; domain->domain.geometry.aperture_end = dma_max_address(); domain->domain.geometry.aperture_end = dma_max_address(pgtable); domain->domain.geometry.force_aperture = true; domain->domain.pgsize_bitmap = domain->iop.pgtbl.cfg.pgsize_bitmap; Loading @@ -2383,8 +2385,16 @@ static struct iommu_domain *do_iommu_domain_alloc(unsigned int type, static struct iommu_domain *amd_iommu_domain_alloc(unsigned int type) { struct iommu_domain *domain; int pgtable = amd_iommu_pgtable; domain = do_iommu_domain_alloc(type, NULL, 0); /* * Force IOMMU v1 page table when allocating * domain for pass-through devices. */ if (type == IOMMU_DOMAIN_UNMANAGED) pgtable = AMD_IOMMU_V1; domain = do_iommu_domain_alloc(type, NULL, 0, pgtable); if (IS_ERR(domain)) return NULL; Loading @@ -2398,11 +2408,36 @@ amd_iommu_domain_alloc_user(struct device *dev, u32 flags, { unsigned int type = IOMMU_DOMAIN_UNMANAGED; struct amd_iommu *iommu = NULL; const u32 supported_flags = IOMMU_HWPT_ALLOC_DIRTY_TRACKING | IOMMU_HWPT_ALLOC_PASID; if (dev) iommu = get_amd_iommu_from_dev(dev); if ((flags & ~IOMMU_HWPT_ALLOC_DIRTY_TRACKING) || parent || user_data) if ((flags & ~supported_flags) || parent || user_data) return ERR_PTR(-EOPNOTSUPP); return do_iommu_domain_alloc(type, dev, flags); /* Allocate domain with v2 page table if IOMMU supports PASID. */ if (flags & IOMMU_HWPT_ALLOC_PASID) { if (!amd_iommu_pasid_supported()) return ERR_PTR(-EOPNOTSUPP); return do_iommu_domain_alloc(type, dev, flags, AMD_IOMMU_V2); } /* Allocate domain with v1 page table for dirty tracking */ if (flags & IOMMU_HWPT_ALLOC_DIRTY_TRACKING) { if (iommu && amd_iommu_hd_support(iommu)) { return do_iommu_domain_alloc(type, dev, flags, AMD_IOMMU_V1); } return ERR_PTR(-EOPNOTSUPP); } /* If nothing specific is required use the kernel commandline default */ return do_iommu_domain_alloc(type, dev, 0, amd_iommu_pgtable); } void amd_iommu_domain_free(struct iommu_domain *dom) Loading Loading @@ -2444,6 +2479,25 @@ static struct iommu_domain blocked_domain = { } }; static struct protection_domain identity_domain; static const struct iommu_domain_ops identity_domain_ops = { .attach_dev = amd_iommu_attach_device, }; void amd_iommu_init_identity_domain(void) { struct iommu_domain *domain = &identity_domain.domain; domain->type = IOMMU_DOMAIN_IDENTITY; domain->ops = &identity_domain_ops; domain->owner = &amd_iommu_ops; identity_domain.id = domain_id_alloc(); protection_domain_init(&identity_domain, NUMA_NO_NODE); } static int amd_iommu_attach_device(struct iommu_domain *dom, struct device *dev) { Loading Loading @@ -2842,6 +2896,7 @@ static int amd_iommu_dev_disable_feature(struct device *dev, const struct iommu_ops amd_iommu_ops = { .capable = amd_iommu_capable, .blocked_domain = &blocked_domain, .identity_domain = &identity_domain.domain, .domain_alloc = amd_iommu_domain_alloc, .domain_alloc_user = amd_iommu_domain_alloc_user, .domain_alloc_sva = amd_iommu_domain_alloc_sva, Loading drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +5 −1 Original line number Diff line number Diff line Loading @@ -3084,7 +3084,8 @@ arm_smmu_domain_alloc_user(struct device *dev, u32 flags, const struct iommu_user_data *user_data) { struct arm_smmu_master *master = dev_iommu_priv_get(dev); const u32 PAGING_FLAGS = IOMMU_HWPT_ALLOC_DIRTY_TRACKING; const u32 PAGING_FLAGS = IOMMU_HWPT_ALLOC_DIRTY_TRACKING | IOMMU_HWPT_ALLOC_PASID; struct arm_smmu_domain *smmu_domain; int ret; Loading @@ -3093,6 +3094,9 @@ arm_smmu_domain_alloc_user(struct device *dev, u32 flags, if (parent || user_data) return ERR_PTR(-EOPNOTSUPP); if (flags & IOMMU_HWPT_ALLOC_PASID) return arm_smmu_domain_alloc_paging(dev); smmu_domain = arm_smmu_domain_alloc(); if (IS_ERR(smmu_domain)) return ERR_CAST(smmu_domain); Loading Loading
drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c +2 −2 Original line number Diff line number Diff line Loading @@ -120,8 +120,8 @@ nvkm_device_tegra_probe_iommu(struct nvkm_device_tegra *tdev) mutex_init(&tdev->iommu.mutex); if (device_iommu_mapped(dev)) { tdev->iommu.domain = iommu_domain_alloc(&platform_bus_type); if (!tdev->iommu.domain) tdev->iommu.domain = iommu_paging_domain_alloc(dev); if (IS_ERR(tdev->iommu.domain)) goto error; /* Loading
drivers/iommu/amd/amd_iommu.h +7 −1 Original line number Diff line number Diff line Loading @@ -46,6 +46,7 @@ extern int amd_iommu_gpt_level; extern unsigned long amd_iommu_pgsize_bitmap; /* Protection domain ops */ void amd_iommu_init_identity_domain(void); struct protection_domain *protection_domain_alloc(unsigned int type, int nid); void protection_domain_free(struct protection_domain *domain); struct iommu_domain *amd_iommu_domain_alloc_sva(struct device *dev, Loading Loading @@ -118,9 +119,14 @@ static inline bool check_feature2(u64 mask) return (amd_iommu_efr2 & mask); } static inline bool amd_iommu_v2_pgtbl_supported(void) { return (check_feature(FEATURE_GIOSUP) && check_feature(FEATURE_GT)); } static inline bool amd_iommu_gt_ppr_supported(void) { return (check_feature(FEATURE_GT) && return (amd_iommu_v2_pgtbl_supported() && check_feature(FEATURE_PPR) && check_feature(FEATURE_EPHSUP)); } Loading
drivers/iommu/amd/init.c +10 −8 Original line number Diff line number Diff line Loading @@ -2070,14 +2070,6 @@ static int __init iommu_init_pci(struct amd_iommu *iommu) init_iommu_perf_ctr(iommu); if (amd_iommu_pgtable == AMD_IOMMU_V2) { if (!check_feature(FEATURE_GIOSUP) || !check_feature(FEATURE_GT)) { pr_warn("Cannot enable v2 page table for DMA-API. Fallback to v1.\n"); amd_iommu_pgtable = AMD_IOMMU_V1; } } if (is_rd890_iommu(iommu->dev)) { int i, j; Loading Loading @@ -2172,6 +2164,9 @@ static int __init amd_iommu_init_pci(void) struct amd_iommu_pci_seg *pci_seg; int ret; /* Init global identity domain before registering IOMMU */ amd_iommu_init_identity_domain(); for_each_iommu(iommu) { ret = iommu_init_pci(iommu); if (ret) { Loading Loading @@ -3087,6 +3082,13 @@ static int __init early_amd_iommu_init(void) FIELD_GET(FEATURE_GATS, amd_iommu_efr) == GUEST_PGTABLE_5_LEVEL) amd_iommu_gpt_level = PAGE_MODE_5_LEVEL; if (amd_iommu_pgtable == AMD_IOMMU_V2) { if (!amd_iommu_v2_pgtbl_supported()) { pr_warn("Cannot enable v2 page table for DMA-API. Fallback to v1.\n"); amd_iommu_pgtable = AMD_IOMMU_V1; } } /* Disable any previously enabled IOMMUs */ if (!is_kdump_kernel() || amd_iommu_disabled) disable_iommus(); Loading
drivers/iommu/amd/iommu.c +98 −43 Original line number Diff line number Diff line Loading @@ -74,6 +74,9 @@ struct kmem_cache *amd_iommu_irq_cache; static void detach_device(struct device *dev); static int amd_iommu_attach_device(struct iommu_domain *dom, struct device *dev); static void set_dte_entry(struct amd_iommu *iommu, struct iommu_dev_data *dev_data); Loading Loading @@ -2263,44 +2266,42 @@ void protection_domain_free(struct protection_domain *domain) kfree(domain); } static void protection_domain_init(struct protection_domain *domain, int nid) { spin_lock_init(&domain->lock); INIT_LIST_HEAD(&domain->dev_list); INIT_LIST_HEAD(&domain->dev_data_list); domain->iop.pgtbl.cfg.amd.nid = nid; } struct protection_domain *protection_domain_alloc(unsigned int type, int nid) { struct io_pgtable_ops *pgtbl_ops; struct protection_domain *domain; int pgtable; domain = kzalloc(sizeof(*domain), GFP_KERNEL); if (!domain) return NULL; domain->id = domain_id_alloc(); if (!domain->id) goto err_free; if (!domain->id) { kfree(domain); return NULL; } spin_lock_init(&domain->lock); INIT_LIST_HEAD(&domain->dev_list); INIT_LIST_HEAD(&domain->dev_data_list); domain->iop.pgtbl.cfg.amd.nid = nid; protection_domain_init(domain, nid); switch (type) { /* No need to allocate io pgtable ops in passthrough mode */ case IOMMU_DOMAIN_IDENTITY: case IOMMU_DOMAIN_SVA: return domain; case IOMMU_DOMAIN_DMA: pgtable = amd_iommu_pgtable; break; /* * Force IOMMU v1 page table when allocating * domain for pass-through devices. */ case IOMMU_DOMAIN_UNMANAGED: pgtable = AMD_IOMMU_V1; break; default: goto err_id; } static int pdom_setup_pgtable(struct protection_domain *domain, unsigned int type, int pgtable) { struct io_pgtable_ops *pgtbl_ops; /* No need to allocate io pgtable ops in passthrough mode */ if (!(type & __IOMMU_DOMAIN_PAGING)) return 0; switch (pgtable) { case AMD_IOMMU_V1: domain->pd_mode = PD_MODE_V1; Loading @@ -2309,25 +2310,20 @@ struct protection_domain *protection_domain_alloc(unsigned int type, int nid) domain->pd_mode = PD_MODE_V2; break; default: goto err_id; return -EINVAL; } pgtbl_ops = alloc_io_pgtable_ops(pgtable, &domain->iop.pgtbl.cfg, domain); if (!pgtbl_ops) goto err_id; return -ENOMEM; return domain; err_id: domain_id_free(domain->id); err_free: kfree(domain); return NULL; return 0; } static inline u64 dma_max_address(void) static inline u64 dma_max_address(int pgtable) { if (amd_iommu_pgtable == AMD_IOMMU_V1) if (pgtable == AMD_IOMMU_V1) return ~0ULL; /* V2 with 4/5 level page table */ Loading @@ -2340,11 +2336,13 @@ static bool amd_iommu_hd_support(struct amd_iommu *iommu) } static struct iommu_domain *do_iommu_domain_alloc(unsigned int type, struct device *dev, u32 flags) struct device *dev, u32 flags, int pgtable) { bool dirty_tracking = flags & IOMMU_HWPT_ALLOC_DIRTY_TRACKING; struct protection_domain *domain; struct amd_iommu *iommu = NULL; int ret; if (dev) iommu = get_amd_iommu_from_dev(dev); Loading @@ -2356,16 +2354,20 @@ static struct iommu_domain *do_iommu_domain_alloc(unsigned int type, if (amd_iommu_snp_en && (type == IOMMU_DOMAIN_IDENTITY)) return ERR_PTR(-EINVAL); if (dirty_tracking && !amd_iommu_hd_support(iommu)) return ERR_PTR(-EOPNOTSUPP); domain = protection_domain_alloc(type, dev ? dev_to_node(dev) : NUMA_NO_NODE); if (!domain) return ERR_PTR(-ENOMEM); ret = pdom_setup_pgtable(domain, type, pgtable); if (ret) { domain_id_free(domain->id); kfree(domain); return ERR_PTR(ret); } domain->domain.geometry.aperture_start = 0; domain->domain.geometry.aperture_end = dma_max_address(); domain->domain.geometry.aperture_end = dma_max_address(pgtable); domain->domain.geometry.force_aperture = true; domain->domain.pgsize_bitmap = domain->iop.pgtbl.cfg.pgsize_bitmap; Loading @@ -2383,8 +2385,16 @@ static struct iommu_domain *do_iommu_domain_alloc(unsigned int type, static struct iommu_domain *amd_iommu_domain_alloc(unsigned int type) { struct iommu_domain *domain; int pgtable = amd_iommu_pgtable; domain = do_iommu_domain_alloc(type, NULL, 0); /* * Force IOMMU v1 page table when allocating * domain for pass-through devices. */ if (type == IOMMU_DOMAIN_UNMANAGED) pgtable = AMD_IOMMU_V1; domain = do_iommu_domain_alloc(type, NULL, 0, pgtable); if (IS_ERR(domain)) return NULL; Loading @@ -2398,11 +2408,36 @@ amd_iommu_domain_alloc_user(struct device *dev, u32 flags, { unsigned int type = IOMMU_DOMAIN_UNMANAGED; struct amd_iommu *iommu = NULL; const u32 supported_flags = IOMMU_HWPT_ALLOC_DIRTY_TRACKING | IOMMU_HWPT_ALLOC_PASID; if (dev) iommu = get_amd_iommu_from_dev(dev); if ((flags & ~IOMMU_HWPT_ALLOC_DIRTY_TRACKING) || parent || user_data) if ((flags & ~supported_flags) || parent || user_data) return ERR_PTR(-EOPNOTSUPP); return do_iommu_domain_alloc(type, dev, flags); /* Allocate domain with v2 page table if IOMMU supports PASID. */ if (flags & IOMMU_HWPT_ALLOC_PASID) { if (!amd_iommu_pasid_supported()) return ERR_PTR(-EOPNOTSUPP); return do_iommu_domain_alloc(type, dev, flags, AMD_IOMMU_V2); } /* Allocate domain with v1 page table for dirty tracking */ if (flags & IOMMU_HWPT_ALLOC_DIRTY_TRACKING) { if (iommu && amd_iommu_hd_support(iommu)) { return do_iommu_domain_alloc(type, dev, flags, AMD_IOMMU_V1); } return ERR_PTR(-EOPNOTSUPP); } /* If nothing specific is required use the kernel commandline default */ return do_iommu_domain_alloc(type, dev, 0, amd_iommu_pgtable); } void amd_iommu_domain_free(struct iommu_domain *dom) Loading Loading @@ -2444,6 +2479,25 @@ static struct iommu_domain blocked_domain = { } }; static struct protection_domain identity_domain; static const struct iommu_domain_ops identity_domain_ops = { .attach_dev = amd_iommu_attach_device, }; void amd_iommu_init_identity_domain(void) { struct iommu_domain *domain = &identity_domain.domain; domain->type = IOMMU_DOMAIN_IDENTITY; domain->ops = &identity_domain_ops; domain->owner = &amd_iommu_ops; identity_domain.id = domain_id_alloc(); protection_domain_init(&identity_domain, NUMA_NO_NODE); } static int amd_iommu_attach_device(struct iommu_domain *dom, struct device *dev) { Loading Loading @@ -2842,6 +2896,7 @@ static int amd_iommu_dev_disable_feature(struct device *dev, const struct iommu_ops amd_iommu_ops = { .capable = amd_iommu_capable, .blocked_domain = &blocked_domain, .identity_domain = &identity_domain.domain, .domain_alloc = amd_iommu_domain_alloc, .domain_alloc_user = amd_iommu_domain_alloc_user, .domain_alloc_sva = amd_iommu_domain_alloc_sva, Loading
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +5 −1 Original line number Diff line number Diff line Loading @@ -3084,7 +3084,8 @@ arm_smmu_domain_alloc_user(struct device *dev, u32 flags, const struct iommu_user_data *user_data) { struct arm_smmu_master *master = dev_iommu_priv_get(dev); const u32 PAGING_FLAGS = IOMMU_HWPT_ALLOC_DIRTY_TRACKING; const u32 PAGING_FLAGS = IOMMU_HWPT_ALLOC_DIRTY_TRACKING | IOMMU_HWPT_ALLOC_PASID; struct arm_smmu_domain *smmu_domain; int ret; Loading @@ -3093,6 +3094,9 @@ arm_smmu_domain_alloc_user(struct device *dev, u32 flags, if (parent || user_data) return ERR_PTR(-EOPNOTSUPP); if (flags & IOMMU_HWPT_ALLOC_PASID) return arm_smmu_domain_alloc_paging(dev); smmu_domain = arm_smmu_domain_alloc(); if (IS_ERR(smmu_domain)) return ERR_CAST(smmu_domain); Loading