Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 358dd8ac authored by Keshavamurthy, Anil S's avatar Keshavamurthy, Anil S Committed by Linus Torvalds
Browse files

intel-iommu: fix for IOMMU early crash



pci_dev's->sysdata is highly overloaded and currently IOMMU is broken due
to IOMMU code depending on this field.

This patch introduces new field in pci_dev's dev.archdata struct to hold
IOMMU specific per device IOMMU private data.

Signed-off-by: default avatarAnil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
Acked-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Greg KH <greg@kroah.com>
Cc: Jeff Garzik <jeff@garzik.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent f76aec76
Loading
Loading
Loading
Loading
+11 −11
Original line number Diff line number Diff line
@@ -1348,7 +1348,7 @@ static void domain_remove_dev_info(struct dmar_domain *domain)
		list_del(&info->link);
		list_del(&info->global);
		if (info->dev)
			info->dev->sysdata = NULL;
			info->dev->dev.archdata.iommu = NULL;
		spin_unlock_irqrestore(&device_domain_lock, flags);

		detach_domain_for_dev(info->domain, info->bus, info->devfn);
@@ -1361,7 +1361,7 @@ static void domain_remove_dev_info(struct dmar_domain *domain)

/*
 * find_domain
 * Note: we use struct pci_dev->sysdata stores the info
 * Note: we use struct pci_dev->dev.archdata.iommu stores the info
 */
struct dmar_domain *
find_domain(struct pci_dev *pdev)
@@ -1369,7 +1369,7 @@ find_domain(struct pci_dev *pdev)
	struct device_domain_info *info;

	/* No lock here, assumes no domain exit in normal case */
	info = pdev->sysdata;
	info = pdev->dev.archdata.iommu;
	if (info)
		return info->domain;
	return NULL;
@@ -1519,7 +1519,7 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw)
	}
	list_add(&info->link, &domain->devices);
	list_add(&info->global, &device_domain_list);
	pdev->sysdata = info;
	pdev->dev.archdata.iommu = info;
	spin_unlock_irqrestore(&device_domain_lock, flags);
	return domain;
error:
@@ -1579,7 +1579,7 @@ static int iommu_prepare_identity_map(struct pci_dev *pdev, u64 start, u64 end)
static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr,
	struct pci_dev *pdev)
{
	if (pdev->sysdata == DUMMY_DEVICE_DOMAIN_INFO)
	if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO)
		return 0;
	return iommu_prepare_identity_map(pdev, rmrr->base_address,
		rmrr->end_address + 1);
@@ -1595,7 +1595,7 @@ static void __init iommu_prepare_gfx_mapping(void)
	int ret;

	for_each_pci_dev(pdev) {
		if (pdev->sysdata == DUMMY_DEVICE_DOMAIN_INFO ||
		if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO ||
				!IS_GFX_DEVICE(pdev))
			continue;
		printk(KERN_INFO "IOMMU: gfx device %s 1-1 mapping\n",
@@ -1836,7 +1836,7 @@ static dma_addr_t intel_map_single(struct device *hwdev, void *addr,
	int prot = 0;

	BUG_ON(dir == DMA_NONE);
	if (pdev->sysdata == DUMMY_DEVICE_DOMAIN_INFO)
	if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO)
		return virt_to_bus(addr);

	domain = get_valid_domain_for_dev(pdev);
@@ -1900,7 +1900,7 @@ static void intel_unmap_single(struct device *dev, dma_addr_t dev_addr,
	unsigned long start_addr;
	struct iova *iova;

	if (pdev->sysdata == DUMMY_DEVICE_DOMAIN_INFO)
	if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO)
		return;
	domain = find_domain(pdev);
	BUG_ON(!domain);
@@ -1974,7 +1974,7 @@ static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sg,
	size_t size = 0;
	void *addr;

	if (pdev->sysdata == DUMMY_DEVICE_DOMAIN_INFO)
	if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO)
		return;

	domain = find_domain(pdev);
@@ -2032,7 +2032,7 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sg,
	unsigned long start_addr;

	BUG_ON(dir == DMA_NONE);
	if (pdev->sysdata == DUMMY_DEVICE_DOMAIN_INFO)
	if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO)
		return intel_nontranslate_map_sg(hwdev, sg, nelems, dir);

	domain = get_valid_domain_for_dev(pdev);
@@ -2234,7 +2234,7 @@ static void __init init_no_remapping_devices(void)
		for (i = 0; i < drhd->devices_cnt; i++) {
			if (!drhd->devices[i])
				continue;
			drhd->devices[i]->sysdata = DUMMY_DEVICE_DOMAIN_INFO;
			drhd->devices[i]->dev.archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO;
		}
	}
}
+3 −0
Original line number Diff line number Diff line
@@ -5,6 +5,9 @@ struct dev_archdata {
#ifdef CONFIG_ACPI
	void	*acpi_handle;
#endif
#ifdef CONFIG_DMAR
	void *iommu; /* hook for IOMMU specific extension */
#endif
};

#endif /* _ASM_X86_DEVICE_H */