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

Commit 59e9b514 authored by Swathi Sridhar's avatar Swathi Sridhar
Browse files

iommu: arm-smmu: Establish smmu device-links with smmu clients



Use the device link framework to establish device-links
between the smmu device and the client devices as part
of the arm_smmu_add_device call where the smmu would
serve as the supplier device and the clients will serve
as the consumer device.Establishing the device link
will help maintain the right order of devices in the
devices_kset and the dpm_list where the consumers follow
the suppliers in the list.Maintaining the right order of
devices in these list is crucial since the shutdown and
suspend/resume callbacks are invoked in the reverse order
of the list.

Change-Id: I85600a0b1c2e562b61b027522c19a63812d7a409
Signed-off-by: default avatarSwathi Sridhar <swatsrid@codeaurora.org>
parent aea35ab9
Loading
Loading
Loading
Loading
+20 −2
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@
#include <linux/acpi_iort.h>
#include <linux/atomic.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/dma-iommu.h>
#include <linux/dma-mapping.h>
#include <linux/err.h>
@@ -2943,6 +2944,7 @@ static int arm_smmu_add_device(struct device *dev)
	struct arm_smmu_device *smmu;
	struct arm_smmu_master_cfg *cfg;
	struct iommu_fwspec *fwspec = dev->iommu_fwspec;
	struct device_link *link;
	int i, ret;

	if (using_legacy_binding) {
@@ -2996,13 +2998,22 @@ static int arm_smmu_add_device(struct device *dev)
	while (i--)
		cfg->smendx[i] = INVALID_SMENDX;

	ret = arm_smmu_master_alloc_smes(dev);
	if (ret)
	link = device_link_add(dev, smmu->dev, DL_FLAG_STATELESS);
	if (!link) {
		dev_err(dev, "error in device link creation between %s & %s\n",
				dev_name(smmu->dev), dev_name(dev));
		ret = -ENODEV;
		goto out_cfg_free;
	}

	ret = arm_smmu_master_alloc_smes(dev);
	if (ret)
		goto out_dev_link_free;
	arm_smmu_power_off(smmu->pwr);
	return 0;

out_dev_link_free:
	device_link_del(link);
out_cfg_free:
	kfree(cfg);
out_pwr_off:
@@ -3016,6 +3027,7 @@ static void arm_smmu_remove_device(struct device *dev)
{
	struct iommu_fwspec *fwspec = dev->iommu_fwspec;
	struct arm_smmu_device *smmu;
	struct device_link *link;

	if (!fwspec || fwspec->ops != &arm_smmu_ops)
		return;
@@ -3026,6 +3038,12 @@ static void arm_smmu_remove_device(struct device *dev)
		return;
	}

	/* Remove the device link between dev and the smmu if any */
	list_for_each_entry(link, &smmu->dev->links.consumers, s_node) {
		if (link->consumer == dev)
			device_link_del(link);
	}

	arm_smmu_master_free_smes(fwspec);
	iommu_group_remove_device(dev);
	kfree(fwspec->iommu_priv);