Ver código fonte

Merge tag 'iommu-fixes-v3.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu

Pull iommu fixes from Joerg Roedel:
 "Fixes for regressions:

   - fix wrong IOMMU enumeration causing some SCSI device drivers
     initialization failures
   - ARM-SMMU fixes for a panic condition and a wrong return value"

* tag 'iommu-fixes-v3.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu:
  iommu/arm-smmu: fix panic in arm_smmu_alloc_init_pte
  iommu/arm-smmu: Return 0 on unmap failure
  iommu/vt-d: fix bug in matching PCI devices with DRHD/RMRR descriptors
  iommu/vt-d: Fix get_domain_for_dev() handling of upstream PCIe bridges
  iommu/vt-d: fix memory leakage caused by commit ea8ea46
Linus Torvalds 11 anos atrás
pai
commit
5269519f9f
3 arquivos alterados com 11 adições e 6 exclusões
  1. 2 2
      drivers/iommu/arm-smmu.c
  2. 2 1
      drivers/iommu/dmar.c
  3. 7 3
      drivers/iommu/intel-iommu.c

+ 2 - 2
drivers/iommu/arm-smmu.c

@@ -1381,7 +1381,7 @@ static int arm_smmu_alloc_init_pmd(struct arm_smmu_device *smmu, pud_t *pud,
 
 
 	do {
 	do {
 		next = pmd_addr_end(addr, end);
 		next = pmd_addr_end(addr, end);
-		ret = arm_smmu_alloc_init_pte(smmu, pmd, addr, end, pfn,
+		ret = arm_smmu_alloc_init_pte(smmu, pmd, addr, next, pfn,
 					      prot, stage);
 					      prot, stage);
 		phys += next - addr;
 		phys += next - addr;
 	} while (pmd++, addr = next, addr < end);
 	} while (pmd++, addr = next, addr < end);
@@ -1499,7 +1499,7 @@ static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova,
 
 
 	ret = arm_smmu_handle_mapping(smmu_domain, iova, 0, size, 0);
 	ret = arm_smmu_handle_mapping(smmu_domain, iova, 0, size, 0);
 	arm_smmu_tlb_inv_context(&smmu_domain->root_cfg);
 	arm_smmu_tlb_inv_context(&smmu_domain->root_cfg);
-	return ret ? ret : size;
+	return ret ? 0 : size;
 }
 }
 
 
 static phys_addr_t arm_smmu_iova_to_phys(struct iommu_domain *domain,
 static phys_addr_t arm_smmu_iova_to_phys(struct iommu_domain *domain,

+ 2 - 1
drivers/iommu/dmar.c

@@ -152,7 +152,8 @@ dmar_alloc_pci_notify_info(struct pci_dev *dev, unsigned long event)
 	info->seg = pci_domain_nr(dev->bus);
 	info->seg = pci_domain_nr(dev->bus);
 	info->level = level;
 	info->level = level;
 	if (event == BUS_NOTIFY_ADD_DEVICE) {
 	if (event == BUS_NOTIFY_ADD_DEVICE) {
-		for (tmp = dev, level--; tmp; tmp = tmp->bus->self) {
+		for (tmp = dev; tmp; tmp = tmp->bus->self) {
+			level--;
 			info->path[level].device = PCI_SLOT(tmp->devfn);
 			info->path[level].device = PCI_SLOT(tmp->devfn);
 			info->path[level].function = PCI_FUNC(tmp->devfn);
 			info->path[level].function = PCI_FUNC(tmp->devfn);
 			if (pci_is_root_bus(tmp->bus))
 			if (pci_is_root_bus(tmp->bus))

+ 7 - 3
drivers/iommu/intel-iommu.c

@@ -1009,11 +1009,13 @@ static struct page *dma_pte_list_pagetables(struct dmar_domain *domain,
 	if (level == 1)
 	if (level == 1)
 		return freelist;
 		return freelist;
 
 
-	for (pte = page_address(pg); !first_pte_in_page(pte); pte++) {
+	pte = page_address(pg);
+	do {
 		if (dma_pte_present(pte) && !dma_pte_superpage(pte))
 		if (dma_pte_present(pte) && !dma_pte_superpage(pte))
 			freelist = dma_pte_list_pagetables(domain, level - 1,
 			freelist = dma_pte_list_pagetables(domain, level - 1,
 							   pte, freelist);
 							   pte, freelist);
-	}
+		pte++;
+	} while (!first_pte_in_page(pte));
 
 
 	return freelist;
 	return freelist;
 }
 }
@@ -2235,7 +2237,9 @@ static struct dmar_domain *get_domain_for_dev(struct device *dev, int gaw)
 				bridge_devfn = dev_tmp->devfn;
 				bridge_devfn = dev_tmp->devfn;
 			}
 			}
 			spin_lock_irqsave(&device_domain_lock, flags);
 			spin_lock_irqsave(&device_domain_lock, flags);
-			info = dmar_search_domain_by_dev_info(segment, bus, devfn);
+			info = dmar_search_domain_by_dev_info(segment,
+							      bridge_bus,
+							      bridge_devfn);
 			if (info) {
 			if (info) {
 				iommu = info->iommu;
 				iommu = info->iommu;
 				domain = info->domain;
 				domain = info->domain;