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

Commit b718cd3d authored by David Woodhouse's avatar David Woodhouse
Browse files

iommu/vt-d: Stop dmar_insert_dev_info() freeing domains on losing race



By moving this into get_domain_for_dev() we can make dmar_insert_dev_info()
suitable for use with "special" domains such as the si_domain, which
currently use domain_add_dev_info().

Signed-off-by: default avatarDavid Woodhouse <David.Woodhouse@intel.com>
parent 64ae892b
Loading
Loading
Loading
Loading
+21 −24
Original line number Diff line number Diff line
@@ -2147,16 +2147,17 @@ dmar_search_domain_by_dev_info(int segment, int bus, int devfn)
	return NULL;
}

static int dmar_insert_dev_info(int segment, int bus, int devfn,
				struct device *dev, struct dmar_domain **domp)
static struct dmar_domain *dmar_insert_dev_info(int segment, int bus, int devfn,
						struct device *dev,
						struct dmar_domain *domain)
{
	struct dmar_domain *found, *domain = *domp;
	struct dmar_domain *found;
	struct device_domain_info *info;
	unsigned long flags;

	info = alloc_devinfo_mem();
	if (!info)
		return -ENOMEM;
		return NULL;

	info->segment = segment;
	info->bus = bus;
@@ -2174,19 +2175,17 @@ static int dmar_insert_dev_info(int segment, int bus, int devfn,
	if (found) {
		spin_unlock_irqrestore(&device_domain_lock, flags);
		free_devinfo_mem(info);
		if (found != domain) {
			domain_exit(domain);
			*domp = found;
		/* Caller must free the original domain */
		return found;
	}
	} else {

	list_add(&info->link, &domain->devices);
	list_add(&info->global, &device_domain_list);
	if (dev)
		dev->archdata.iommu = info;
	spin_unlock_irqrestore(&device_domain_lock, flags);
	}

	return 0;
	return domain;
}

/* domain is initialized */
@@ -2245,21 +2244,19 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw)

	/* register pcie-to-pci device */
	if (dev_tmp) {
		if (dmar_insert_dev_info(segment, bus, devfn, NULL, &domain))
		domain = dmar_insert_dev_info(segment, bus, devfn, NULL, domain);
		if (!domain)
			goto error;
		else
			free = NULL;
	}

found_domain:
	if (dmar_insert_dev_info(segment, pdev->bus->number, pdev->devfn,
				 &pdev->dev, &domain) == 0)
		return domain;
	domain = dmar_insert_dev_info(segment, pdev->bus->number, pdev->devfn,
				      &pdev->dev, domain);
error:
	if (free)
	if (free != domain)
		domain_exit(free);
	/* recheck it here, maybe others set it */
	return find_domain(&pdev->dev);

	return domain;
}

static int iommu_identity_mapping;