Pārlūkot izejas kodu

Merge tag 'iommu-fixes-v4.17-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu

Pull iommu fixes from Joerg Roedel:

 - fix a compile warning in the AMD IOMMU driver with irq remapping
   disabled

 - fix for VT-d interrupt remapping and invalidation size (caused a
   BUG_ON when trying to invalidate more than 4GB)

 - build fix and a regression fix for broken graphics with old DTS for
   the rockchip iommu driver

 - a revert in the PCI window reservation code which fixes a regression
   with VFIO.

* tag 'iommu-fixes-v4.17-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu:
  iommu: rockchip: fix building without CONFIG_OF
  iommu/vt-d: Use WARN_ON_ONCE instead of BUG_ON in qi_flush_dev_iotlb()
  iommu/vt-d: fix shift-out-of-bounds in bug checking
  iommu/dma: Move PCI window region reservation back into dma specific path.
  iommu/rockchip: Make clock handling optional
  iommu/amd: Hide unused iommu_table_lock
  iommu/vt-d: Fix usage of force parameter in intel_ir_reconfigure_irte()
Linus Torvalds 7 gadi atpakaļ
vecāks
revīzija
772d4f84c6

+ 1 - 1
drivers/iommu/amd_iommu.c

@@ -83,7 +83,6 @@
 
 
 static DEFINE_SPINLOCK(amd_iommu_devtable_lock);
 static DEFINE_SPINLOCK(amd_iommu_devtable_lock);
 static DEFINE_SPINLOCK(pd_bitmap_lock);
 static DEFINE_SPINLOCK(pd_bitmap_lock);
-static DEFINE_SPINLOCK(iommu_table_lock);
 
 
 /* List of all available dev_data structures */
 /* List of all available dev_data structures */
 static LLIST_HEAD(dev_data_list);
 static LLIST_HEAD(dev_data_list);
@@ -3562,6 +3561,7 @@ EXPORT_SYMBOL(amd_iommu_device_info);
  *****************************************************************************/
  *****************************************************************************/
 
 
 static struct irq_chip amd_ir_chip;
 static struct irq_chip amd_ir_chip;
+static DEFINE_SPINLOCK(iommu_table_lock);
 
 
 static void set_dte_irq_entry(u16 devid, struct irq_remap_table *table)
 static void set_dte_irq_entry(u16 devid, struct irq_remap_table *table)
 {
 {

+ 25 - 29
drivers/iommu/dma-iommu.c

@@ -167,40 +167,16 @@ EXPORT_SYMBOL(iommu_put_dma_cookie);
  * @list: Reserved region list from iommu_get_resv_regions()
  * @list: Reserved region list from iommu_get_resv_regions()
  *
  *
  * IOMMU drivers can use this to implement their .get_resv_regions callback
  * IOMMU drivers can use this to implement their .get_resv_regions callback
- * for general non-IOMMU-specific reservations. Currently, this covers host
- * bridge windows for PCI devices and GICv3 ITS region reservation on ACPI
- * based ARM platforms that may require HW MSI reservation.
+ * for general non-IOMMU-specific reservations. Currently, this covers GICv3
+ * ITS region reservation on ACPI based ARM platforms that may require HW MSI
+ * reservation.
  */
  */
 void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list)
 void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list)
 {
 {
-	struct pci_host_bridge *bridge;
-	struct resource_entry *window;
-
-	if (!is_of_node(dev->iommu_fwspec->iommu_fwnode) &&
-		iort_iommu_msi_get_resv_regions(dev, list) < 0)
-		return;
-
-	if (!dev_is_pci(dev))
-		return;
-
-	bridge = pci_find_host_bridge(to_pci_dev(dev)->bus);
-	resource_list_for_each_entry(window, &bridge->windows) {
-		struct iommu_resv_region *region;
-		phys_addr_t start;
-		size_t length;
-
-		if (resource_type(window->res) != IORESOURCE_MEM)
-			continue;
 
 
-		start = window->res->start - window->offset;
-		length = window->res->end - window->res->start + 1;
-		region = iommu_alloc_resv_region(start, length, 0,
-				IOMMU_RESV_RESERVED);
-		if (!region)
-			return;
+	if (!is_of_node(dev->iommu_fwspec->iommu_fwnode))
+		iort_iommu_msi_get_resv_regions(dev, list);
 
 
-		list_add_tail(&region->list, list);
-	}
 }
 }
 EXPORT_SYMBOL(iommu_dma_get_resv_regions);
 EXPORT_SYMBOL(iommu_dma_get_resv_regions);
 
 
@@ -229,6 +205,23 @@ static int cookie_init_hw_msi_region(struct iommu_dma_cookie *cookie,
 	return 0;
 	return 0;
 }
 }
 
 
+static void iova_reserve_pci_windows(struct pci_dev *dev,
+		struct iova_domain *iovad)
+{
+	struct pci_host_bridge *bridge = pci_find_host_bridge(dev->bus);
+	struct resource_entry *window;
+	unsigned long lo, hi;
+
+	resource_list_for_each_entry(window, &bridge->windows) {
+		if (resource_type(window->res) != IORESOURCE_MEM)
+			continue;
+
+		lo = iova_pfn(iovad, window->res->start - window->offset);
+		hi = iova_pfn(iovad, window->res->end - window->offset);
+		reserve_iova(iovad, lo, hi);
+	}
+}
+
 static int iova_reserve_iommu_regions(struct device *dev,
 static int iova_reserve_iommu_regions(struct device *dev,
 		struct iommu_domain *domain)
 		struct iommu_domain *domain)
 {
 {
@@ -238,6 +231,9 @@ static int iova_reserve_iommu_regions(struct device *dev,
 	LIST_HEAD(resv_regions);
 	LIST_HEAD(resv_regions);
 	int ret = 0;
 	int ret = 0;
 
 
+	if (dev_is_pci(dev))
+		iova_reserve_pci_windows(to_pci_dev(dev), iovad);
+
 	iommu_get_resv_regions(dev, &resv_regions);
 	iommu_get_resv_regions(dev, &resv_regions);
 	list_for_each_entry(region, &resv_regions, list) {
 	list_for_each_entry(region, &resv_regions, list) {
 		unsigned long lo, hi;
 		unsigned long lo, hi;

+ 1 - 1
drivers/iommu/dmar.c

@@ -1345,7 +1345,7 @@ void qi_flush_dev_iotlb(struct intel_iommu *iommu, u16 sid, u16 qdep,
 	struct qi_desc desc;
 	struct qi_desc desc;
 
 
 	if (mask) {
 	if (mask) {
-		BUG_ON(addr & ((1 << (VTD_PAGE_SHIFT + mask)) - 1));
+		WARN_ON_ONCE(addr & ((1ULL << (VTD_PAGE_SHIFT + mask)) - 1));
 		addr |= (1ULL << (VTD_PAGE_SHIFT + mask - 1)) - 1;
 		addr |= (1ULL << (VTD_PAGE_SHIFT + mask - 1)) - 1;
 		desc.high = QI_DEV_IOTLB_ADDR(addr) | QI_DEV_IOTLB_SIZE;
 		desc.high = QI_DEV_IOTLB_ADDR(addr) | QI_DEV_IOTLB_SIZE;
 	} else
 	} else

+ 1 - 1
drivers/iommu/intel_irq_remapping.c

@@ -1136,7 +1136,7 @@ static void intel_ir_reconfigure_irte(struct irq_data *irqd, bool force)
 	irte->dest_id = IRTE_DEST(cfg->dest_apicid);
 	irte->dest_id = IRTE_DEST(cfg->dest_apicid);
 
 
 	/* Update the hardware only if the interrupt is in remapped mode. */
 	/* Update the hardware only if the interrupt is in remapped mode. */
-	if (!force || ir_data->irq_2_iommu.mode == IRQ_REMAPPING)
+	if (force || ir_data->irq_2_iommu.mode == IRQ_REMAPPING)
 		modify_irte(&ir_data->irq_2_iommu, irte);
 		modify_irte(&ir_data->irq_2_iommu, irte);
 }
 }
 
 

+ 9 - 2
drivers/iommu/rockchip-iommu.c

@@ -1098,7 +1098,7 @@ static int rk_iommu_of_xlate(struct device *dev,
 	data->iommu = platform_get_drvdata(iommu_dev);
 	data->iommu = platform_get_drvdata(iommu_dev);
 	dev->archdata.iommu = data;
 	dev->archdata.iommu = data;
 
 
-	of_dev_put(iommu_dev);
+	platform_device_put(iommu_dev);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -1175,8 +1175,15 @@ static int rk_iommu_probe(struct platform_device *pdev)
 	for (i = 0; i < iommu->num_clocks; ++i)
 	for (i = 0; i < iommu->num_clocks; ++i)
 		iommu->clocks[i].id = rk_iommu_clocks[i];
 		iommu->clocks[i].id = rk_iommu_clocks[i];
 
 
+	/*
+	 * iommu clocks should be present for all new devices and devicetrees
+	 * but there are older devicetrees without clocks out in the wild.
+	 * So clocks as optional for the time being.
+	 */
 	err = devm_clk_bulk_get(iommu->dev, iommu->num_clocks, iommu->clocks);
 	err = devm_clk_bulk_get(iommu->dev, iommu->num_clocks, iommu->clocks);
-	if (err)
+	if (err == -ENOENT)
+		iommu->num_clocks = 0;
+	else if (err)
 		return err;
 		return err;
 
 
 	err = clk_bulk_prepare(iommu->num_clocks, iommu->clocks);
 	err = clk_bulk_prepare(iommu->num_clocks, iommu->clocks);