Loading drivers/iommu/arm-smmu.c +37 −22 Original line number Diff line number Diff line Loading @@ -317,8 +317,8 @@ #define FSR_AFF (1 << 2) #define FSR_TF (1 << 1) #define FSR_IGN (FSR_AFF | FSR_ASF | FSR_TLBMCF | \ FSR_TLBLKF) #define FSR_IGN (FSR_AFF | FSR_ASF | \ FSR_TLBMCF | FSR_TLBLKF) #define FSR_FAULT (FSR_MULTI | FSR_SS | FSR_UUT | \ FSR_EF | FSR_PF | FSR_TF | FSR_IGN) Loading Loading @@ -413,6 +413,7 @@ static struct arm_smmu_option_prop arm_smmu_options [] = { static void parse_driver_options(struct arm_smmu_device *smmu) { int i = 0; do { if (of_property_read_bool(smmu->dev->of_node, arm_smmu_options[i].prop)) { Loading @@ -427,6 +428,7 @@ static struct device *dev_get_master_dev(struct device *dev) { if (dev_is_pci(dev)) { struct pci_bus *bus = to_pci_dev(dev)->bus; while (!pci_is_root_bus(bus)) bus = bus->parent; return bus->bridge->parent; Loading @@ -442,6 +444,7 @@ static struct arm_smmu_master *find_smmu_master(struct arm_smmu_device *smmu, while (node) { struct arm_smmu_master *master; master = container_of(node, struct arm_smmu_master, node); if (dev_node < master->of_node) Loading Loading @@ -475,8 +478,8 @@ static int insert_smmu_master(struct arm_smmu_device *smmu, new = &smmu->masters.rb_node; parent = NULL; while (*new) { struct arm_smmu_master *this; this = container_of(*new, struct arm_smmu_master, node); struct arm_smmu_master *this = container_of(*new, struct arm_smmu_master, node); parent = *new; if (master->of_node < this->of_node) Loading Loading @@ -954,7 +957,7 @@ static int arm_smmu_domain_init(struct iommu_domain *domain) if (!smmu_domain) return -ENOMEM; pgd = kzalloc(PTRS_PER_PGD * sizeof(pgd_t), GFP_KERNEL); pgd = kcalloc(PTRS_PER_PGD, sizeof(pgd_t), GFP_KERNEL); if (!pgd) goto out_free_domain; smmu_domain->cfg.pgd = pgd; Loading @@ -971,6 +974,7 @@ out_free_domain: static void arm_smmu_free_ptes(pmd_t *pmd) { pgtable_t table = pmd_pgtable(*pmd); pgtable_page_dtor(table); __free_page(table); } Loading Loading @@ -1057,7 +1061,7 @@ static int arm_smmu_master_configure_smrs(struct arm_smmu_device *smmu, if (cfg->smrs) return -EEXIST; smrs = kmalloc(sizeof(*smrs) * cfg->num_streamids, GFP_KERNEL); smrs = kmalloc_array(cfg->num_streamids, sizeof(*smrs), GFP_KERNEL); if (!smrs) { dev_err(smmu->dev, "failed to allocate %d SMRs\n", cfg->num_streamids); Loading Loading @@ -1107,6 +1111,7 @@ static void arm_smmu_master_free_smrs(struct arm_smmu_device *smmu, /* Invalidate the SMRs before freeing back to the allocator */ for (i = 0; i < cfg->num_streamids; ++i) { u8 idx = smrs[i].idx; writel_relaxed(~SMR_VALID, gr0_base + ARM_SMMU_GR0_SMR(idx)); __arm_smmu_free_bitmap(smmu->smr_map, idx); } Loading @@ -1123,6 +1128,7 @@ static void arm_smmu_bypass_stream_mapping(struct arm_smmu_device *smmu, for (i = 0; i < cfg->num_streamids; ++i) { u16 sid = cfg->streamids[i]; writel_relaxed(S2CR_TYPE_BYPASS, gr0_base + ARM_SMMU_GR0_S2CR(sid)); } Loading @@ -1141,6 +1147,7 @@ static int arm_smmu_domain_add_master(struct arm_smmu_domain *smmu_domain, for (i = 0; i < cfg->num_streamids; ++i) { u32 idx, s2cr; idx = cfg->smrs ? cfg->smrs[i].idx : cfg->streamids[i]; s2cr = S2CR_TYPE_TRANS | (smmu_domain->cfg.cbndx << S2CR_CBNDX_SHIFT); Loading Loading @@ -1235,6 +1242,7 @@ static int arm_smmu_alloc_init_pte(struct arm_smmu_device *smmu, pmd_t *pmd, if (pmd_none(*pmd)) { /* Allocate a new set of tables */ pgtable_t table = alloc_page(GFP_ATOMIC|__GFP_ZERO); if (!table) return -ENOMEM; Loading Loading @@ -1300,6 +1308,7 @@ static int arm_smmu_alloc_init_pte(struct arm_smmu_device *smmu, pmd_t *pmd, */ do { int i = 1; pteval &= ~ARM_SMMU_PTE_CONT; if (arm_smmu_pte_is_contiguous_range(addr, end)) { Loading @@ -1314,7 +1323,8 @@ static int arm_smmu_alloc_init_pte(struct arm_smmu_device *smmu, pmd_t *pmd, idx &= ~(ARM_SMMU_PTE_CONT_ENTRIES - 1); cont_start = pmd_page_vaddr(*pmd) + idx; for (j = 0; j < ARM_SMMU_PTE_CONT_ENTRIES; ++j) pte_val(*(cont_start + j)) &= ~ARM_SMMU_PTE_CONT; pte_val(*(cont_start + j)) &= ~ARM_SMMU_PTE_CONT; arm_smmu_flush_pgtable(smmu, cont_start, sizeof(*pte) * Loading Loading @@ -1617,7 +1627,8 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu) /* Mark all SMRn as invalid and all S2CRn as bypass */ for (i = 0; i < smmu->num_mapping_groups; ++i) { writel_relaxed(~SMR_VALID, gr0_base + ARM_SMMU_GR0_SMR(i)); writel_relaxed(S2CR_TYPE_BYPASS, gr0_base + ARM_SMMU_GR0_S2CR(i)); writel_relaxed(S2CR_TYPE_BYPASS, gr0_base + ARM_SMMU_GR0_S2CR(i)); } /* Make sure all context banks are disabled and clear CB_FSR */ Loading Loading @@ -1757,11 +1768,13 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) smmu->pagesize = (id & ID1_PAGESIZE) ? SZ_64K : SZ_4K; /* Check for size mismatch of SMMU address space from mapped region */ size = 1 << (((id >> ID1_NUMPAGENDXB_SHIFT) & ID1_NUMPAGENDXB_MASK) + 1); size = 1 << (((id >> ID1_NUMPAGENDXB_SHIFT) & ID1_NUMPAGENDXB_MASK) + 1); size *= (smmu->pagesize << 1); if (smmu->size != size) dev_warn(smmu->dev, "SMMU address space size (0x%lx) differs " "from mapped region size (0x%lx)!\n", size, smmu->size); dev_warn(smmu->dev, "SMMU address space size (0x%lx) differs from mapped region size (0x%lx)!\n", size, smmu->size); smmu->num_s2_context_banks = (id >> ID1_NUMS2CB_SHIFT) & ID1_NUMS2CB_MASK; Loading @@ -1782,14 +1795,14 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) * allocation (PTRS_PER_PGD). */ #ifdef CONFIG_64BIT smmu->s1_output_size = min((unsigned long)VA_BITS, size); smmu->s1_output_size = min_t(unsigned long, VA_BITS, size); #else smmu->s1_output_size = min(32UL, size); #endif /* The stage-2 output mask is also applied for bypass */ size = arm_smmu_id_size_to_bits((id >> ID2_OAS_SHIFT) & ID2_OAS_MASK); smmu->s2_output_size = min((unsigned long)PHYS_MASK_SHIFT, size); smmu->s2_output_size = min_t(unsigned long, PHYS_MASK_SHIFT, size); if (smmu->version == 1) { smmu->input_size = 32; Loading @@ -1813,7 +1826,8 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) dev_notice(smmu->dev, "\t%lu-bit VA, %lu-bit IPA, %lu-bit PA\n", smmu->input_size, smmu->s1_output_size, smmu->s2_output_size); smmu->input_size, smmu->s1_output_size, smmu->s2_output_size); return 0; } Loading Loading @@ -1867,6 +1881,7 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev) for (i = 0; i < num_irqs; ++i) { int irq = platform_get_irq(pdev, i); if (irq < 0) { dev_err(dev, "failed to get irq index %d\n", i); return -ENODEV; Loading Loading @@ -1932,8 +1947,8 @@ out_free_irqs: out_put_masters: for (node = rb_first(&smmu->masters); node; node = rb_next(node)) { struct arm_smmu_master *master; master = container_of(node, struct arm_smmu_master, node); struct arm_smmu_master *master = container_of(node, struct arm_smmu_master, node); of_node_put(master->of_node); } Loading Loading @@ -1961,8 +1976,8 @@ static int arm_smmu_device_remove(struct platform_device *pdev) return -ENODEV; for (node = rb_first(&smmu->masters); node; node = rb_next(node)) { struct arm_smmu_master *master; master = container_of(node, struct arm_smmu_master, node); struct arm_smmu_master *master = container_of(node, struct arm_smmu_master, node); of_node_put(master->of_node); } Loading Loading
drivers/iommu/arm-smmu.c +37 −22 Original line number Diff line number Diff line Loading @@ -317,8 +317,8 @@ #define FSR_AFF (1 << 2) #define FSR_TF (1 << 1) #define FSR_IGN (FSR_AFF | FSR_ASF | FSR_TLBMCF | \ FSR_TLBLKF) #define FSR_IGN (FSR_AFF | FSR_ASF | \ FSR_TLBMCF | FSR_TLBLKF) #define FSR_FAULT (FSR_MULTI | FSR_SS | FSR_UUT | \ FSR_EF | FSR_PF | FSR_TF | FSR_IGN) Loading Loading @@ -413,6 +413,7 @@ static struct arm_smmu_option_prop arm_smmu_options [] = { static void parse_driver_options(struct arm_smmu_device *smmu) { int i = 0; do { if (of_property_read_bool(smmu->dev->of_node, arm_smmu_options[i].prop)) { Loading @@ -427,6 +428,7 @@ static struct device *dev_get_master_dev(struct device *dev) { if (dev_is_pci(dev)) { struct pci_bus *bus = to_pci_dev(dev)->bus; while (!pci_is_root_bus(bus)) bus = bus->parent; return bus->bridge->parent; Loading @@ -442,6 +444,7 @@ static struct arm_smmu_master *find_smmu_master(struct arm_smmu_device *smmu, while (node) { struct arm_smmu_master *master; master = container_of(node, struct arm_smmu_master, node); if (dev_node < master->of_node) Loading Loading @@ -475,8 +478,8 @@ static int insert_smmu_master(struct arm_smmu_device *smmu, new = &smmu->masters.rb_node; parent = NULL; while (*new) { struct arm_smmu_master *this; this = container_of(*new, struct arm_smmu_master, node); struct arm_smmu_master *this = container_of(*new, struct arm_smmu_master, node); parent = *new; if (master->of_node < this->of_node) Loading Loading @@ -954,7 +957,7 @@ static int arm_smmu_domain_init(struct iommu_domain *domain) if (!smmu_domain) return -ENOMEM; pgd = kzalloc(PTRS_PER_PGD * sizeof(pgd_t), GFP_KERNEL); pgd = kcalloc(PTRS_PER_PGD, sizeof(pgd_t), GFP_KERNEL); if (!pgd) goto out_free_domain; smmu_domain->cfg.pgd = pgd; Loading @@ -971,6 +974,7 @@ out_free_domain: static void arm_smmu_free_ptes(pmd_t *pmd) { pgtable_t table = pmd_pgtable(*pmd); pgtable_page_dtor(table); __free_page(table); } Loading Loading @@ -1057,7 +1061,7 @@ static int arm_smmu_master_configure_smrs(struct arm_smmu_device *smmu, if (cfg->smrs) return -EEXIST; smrs = kmalloc(sizeof(*smrs) * cfg->num_streamids, GFP_KERNEL); smrs = kmalloc_array(cfg->num_streamids, sizeof(*smrs), GFP_KERNEL); if (!smrs) { dev_err(smmu->dev, "failed to allocate %d SMRs\n", cfg->num_streamids); Loading Loading @@ -1107,6 +1111,7 @@ static void arm_smmu_master_free_smrs(struct arm_smmu_device *smmu, /* Invalidate the SMRs before freeing back to the allocator */ for (i = 0; i < cfg->num_streamids; ++i) { u8 idx = smrs[i].idx; writel_relaxed(~SMR_VALID, gr0_base + ARM_SMMU_GR0_SMR(idx)); __arm_smmu_free_bitmap(smmu->smr_map, idx); } Loading @@ -1123,6 +1128,7 @@ static void arm_smmu_bypass_stream_mapping(struct arm_smmu_device *smmu, for (i = 0; i < cfg->num_streamids; ++i) { u16 sid = cfg->streamids[i]; writel_relaxed(S2CR_TYPE_BYPASS, gr0_base + ARM_SMMU_GR0_S2CR(sid)); } Loading @@ -1141,6 +1147,7 @@ static int arm_smmu_domain_add_master(struct arm_smmu_domain *smmu_domain, for (i = 0; i < cfg->num_streamids; ++i) { u32 idx, s2cr; idx = cfg->smrs ? cfg->smrs[i].idx : cfg->streamids[i]; s2cr = S2CR_TYPE_TRANS | (smmu_domain->cfg.cbndx << S2CR_CBNDX_SHIFT); Loading Loading @@ -1235,6 +1242,7 @@ static int arm_smmu_alloc_init_pte(struct arm_smmu_device *smmu, pmd_t *pmd, if (pmd_none(*pmd)) { /* Allocate a new set of tables */ pgtable_t table = alloc_page(GFP_ATOMIC|__GFP_ZERO); if (!table) return -ENOMEM; Loading Loading @@ -1300,6 +1308,7 @@ static int arm_smmu_alloc_init_pte(struct arm_smmu_device *smmu, pmd_t *pmd, */ do { int i = 1; pteval &= ~ARM_SMMU_PTE_CONT; if (arm_smmu_pte_is_contiguous_range(addr, end)) { Loading @@ -1314,7 +1323,8 @@ static int arm_smmu_alloc_init_pte(struct arm_smmu_device *smmu, pmd_t *pmd, idx &= ~(ARM_SMMU_PTE_CONT_ENTRIES - 1); cont_start = pmd_page_vaddr(*pmd) + idx; for (j = 0; j < ARM_SMMU_PTE_CONT_ENTRIES; ++j) pte_val(*(cont_start + j)) &= ~ARM_SMMU_PTE_CONT; pte_val(*(cont_start + j)) &= ~ARM_SMMU_PTE_CONT; arm_smmu_flush_pgtable(smmu, cont_start, sizeof(*pte) * Loading Loading @@ -1617,7 +1627,8 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu) /* Mark all SMRn as invalid and all S2CRn as bypass */ for (i = 0; i < smmu->num_mapping_groups; ++i) { writel_relaxed(~SMR_VALID, gr0_base + ARM_SMMU_GR0_SMR(i)); writel_relaxed(S2CR_TYPE_BYPASS, gr0_base + ARM_SMMU_GR0_S2CR(i)); writel_relaxed(S2CR_TYPE_BYPASS, gr0_base + ARM_SMMU_GR0_S2CR(i)); } /* Make sure all context banks are disabled and clear CB_FSR */ Loading Loading @@ -1757,11 +1768,13 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) smmu->pagesize = (id & ID1_PAGESIZE) ? SZ_64K : SZ_4K; /* Check for size mismatch of SMMU address space from mapped region */ size = 1 << (((id >> ID1_NUMPAGENDXB_SHIFT) & ID1_NUMPAGENDXB_MASK) + 1); size = 1 << (((id >> ID1_NUMPAGENDXB_SHIFT) & ID1_NUMPAGENDXB_MASK) + 1); size *= (smmu->pagesize << 1); if (smmu->size != size) dev_warn(smmu->dev, "SMMU address space size (0x%lx) differs " "from mapped region size (0x%lx)!\n", size, smmu->size); dev_warn(smmu->dev, "SMMU address space size (0x%lx) differs from mapped region size (0x%lx)!\n", size, smmu->size); smmu->num_s2_context_banks = (id >> ID1_NUMS2CB_SHIFT) & ID1_NUMS2CB_MASK; Loading @@ -1782,14 +1795,14 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) * allocation (PTRS_PER_PGD). */ #ifdef CONFIG_64BIT smmu->s1_output_size = min((unsigned long)VA_BITS, size); smmu->s1_output_size = min_t(unsigned long, VA_BITS, size); #else smmu->s1_output_size = min(32UL, size); #endif /* The stage-2 output mask is also applied for bypass */ size = arm_smmu_id_size_to_bits((id >> ID2_OAS_SHIFT) & ID2_OAS_MASK); smmu->s2_output_size = min((unsigned long)PHYS_MASK_SHIFT, size); smmu->s2_output_size = min_t(unsigned long, PHYS_MASK_SHIFT, size); if (smmu->version == 1) { smmu->input_size = 32; Loading @@ -1813,7 +1826,8 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) dev_notice(smmu->dev, "\t%lu-bit VA, %lu-bit IPA, %lu-bit PA\n", smmu->input_size, smmu->s1_output_size, smmu->s2_output_size); smmu->input_size, smmu->s1_output_size, smmu->s2_output_size); return 0; } Loading Loading @@ -1867,6 +1881,7 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev) for (i = 0; i < num_irqs; ++i) { int irq = platform_get_irq(pdev, i); if (irq < 0) { dev_err(dev, "failed to get irq index %d\n", i); return -ENODEV; Loading Loading @@ -1932,8 +1947,8 @@ out_free_irqs: out_put_masters: for (node = rb_first(&smmu->masters); node; node = rb_next(node)) { struct arm_smmu_master *master; master = container_of(node, struct arm_smmu_master, node); struct arm_smmu_master *master = container_of(node, struct arm_smmu_master, node); of_node_put(master->of_node); } Loading Loading @@ -1961,8 +1976,8 @@ static int arm_smmu_device_remove(struct platform_device *pdev) return -ENODEV; for (node = rb_first(&smmu->masters); node; node = rb_next(node)) { struct arm_smmu_master *master; master = container_of(node, struct arm_smmu_master, node); struct arm_smmu_master *master = container_of(node, struct arm_smmu_master, node); of_node_put(master->of_node); } Loading