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

Commit 121a9a11 authored by Patrick Daly's avatar Patrick Daly
Browse files

arm64: dma-mapping: Clean up arm_iommu_attach_device() call flow



Previously the code assumed that iommu_attach_group() would occur after
setting up any dma-specific data structures. But there are several places
where to satisfy this requirement we attach, check some iommu attribute,
and then detach. This is not very clean, so improve it.

Change-Id: I5f115217c892716e3f3911b8177f530a64873267
Signed-off-by: default avatarPatrick Daly <pdaly@codeaurora.org>
parent 36c547af
Loading
Loading
Loading
Loading
+18 −24
Original line number Diff line number Diff line
@@ -1979,26 +1979,18 @@ static int upstream_iommu_init_mapping(struct device *dev,
					struct dma_iommu_mapping *mapping)
{
	struct iommu_domain *domain = mapping->domain;
	struct iommu_group *group = dev->iommu_group;
	dma_addr_t base = mapping->base;
	u64 size = mapping->bits << PAGE_SHIFT;

	if (iommu_get_dma_cookie(domain))
		return -EINVAL;

	/* Need to attach to get geometry */
	if (iommu_attach_group(domain, group))
		goto out_put_cookie;

	if (iommu_dma_init_domain(domain, base, size, dev))
		goto out_detach_group;
		goto out_put_cookie;

	mapping->ops = &iommu_dma_ops;
	iommu_detach_group(domain, group);
	return 0;

out_detach_group:
	iommu_detach_group(domain, group);
out_put_cookie:
	iommu_put_dma_cookie(domain);
	return -EINVAL;
@@ -2060,20 +2052,8 @@ static int arm_iommu_init_mapping(struct device *dev,
{
	int err = -EINVAL;
	int s1_bypass = 0, is_fast = 0, is_upstream = 0;
	struct iommu_group *group;
	dma_addr_t iova_end;

	group = dev->iommu_group;
	if (!group) {
		dev_err(dev, "No iommu associated with device\n");
		return -EINVAL;
	}

	if (iommu_get_domain_for_dev(dev)) {
		dev_err(dev, "Device already attached to other iommu_domain\n");
		return -EINVAL;
	}

	if (mapping->init) {
		kref_get(&mapping->kref);
		return 0;
@@ -2128,14 +2108,28 @@ int arm_iommu_attach_device(struct device *dev,
			    struct dma_iommu_mapping *mapping)
{
	int err;
	struct iommu_domain *domain = mapping->domain;
	struct iommu_group *group = dev->iommu_group;

	err = arm_iommu_init_mapping(dev, mapping);
	if (!group) {
		dev_err(dev, "No iommu associated with device\n");
		return -EINVAL;
	}

	if (iommu_get_domain_for_dev(dev)) {
		dev_err(dev, "Device already attached to other iommu_domain\n");
		return -EINVAL;
	}

	err = iommu_attach_group(domain, group);
	if (err)
		return err;

	err = iommu_attach_group(mapping->domain, dev->iommu_group);
	if (err)
	err = arm_iommu_init_mapping(dev, mapping);
	if (err) {
		iommu_detach_group(domain, group);
		return err;
	}

	dev->archdata.mapping = mapping;
	set_dma_ops(dev, mapping->ops);
+2 −28
Original line number Diff line number Diff line
@@ -870,7 +870,6 @@ int fast_smmu_init_mapping(struct device *dev,
{
	int err;
	struct iommu_domain *domain = mapping->domain;
	struct iommu_group *group;
	struct iommu_pgtbl_info info;
	u64 size = (u64)mapping->bits << PAGE_SHIFT;

@@ -887,51 +886,26 @@ int fast_smmu_init_mapping(struct device *dev,

	fast_smmu_reserve_pci_windows(dev, mapping->fast);

	group = dev->iommu_group;
	if (!group) {
		dev_err(dev, "No iommu associated with device\n");
		err = -ENODEV;
		goto release_mapping;
	}

	if (iommu_get_domain_for_dev(dev)) {
		dev_err(dev, "Device already attached to other iommu_domain\n");
		err = -EINVAL;
		goto release_mapping;
	}

	/*
	 * Need to attach prior to calling DOMAIN_ATTR_PGTBL_INFO and then
	 * detach to be in the expected state. Its a bit messy.
	 */
	if (iommu_attach_group(mapping->domain, group)) {
		err = -EINVAL;
		goto release_mapping;
	}

	if (iommu_domain_get_attr(domain, DOMAIN_ATTR_PGTBL_INFO,
				  &info)) {
		dev_err(dev, "Couldn't get page table info\n");
		err = -EINVAL;
		goto detach_group;
		goto release_mapping;
	}
	mapping->fast->pgtbl_pmds = info.pmds;

	if (iommu_domain_get_attr(domain, DOMAIN_ATTR_PAGE_TABLE_IS_COHERENT,
				  &mapping->fast->is_smmu_pt_coherent)) {
		err = -EINVAL;
		goto detach_group;
		goto release_mapping;
	}

	mapping->fast->notifier.notifier_call = fast_smmu_notify;
	av8l_register_notify(&mapping->fast->notifier);

	iommu_detach_group(mapping->domain, group);
	mapping->ops = &fast_smmu_dma_ops;
	return 0;

detach_group:
	iommu_detach_group(mapping->domain, group);
release_mapping:
	kfree(mapping->fast->bitmap);
	kfree(mapping->fast);