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

Commit fa26bd56 authored by Swathi Sridhar's avatar Swathi Sridhar Committed by Vijayanand Jitta
Browse files

iommu: arm-smmu: Introduce a new mutex in arm_smmu_device structure



During a default attach for a device, the current implementation
tries to acquire the stream_map_mutex lock once while fetching
the first available smr in arm_smmu_master_alloc_smes and it
tries to acquire again during arm_smmu_domain_context_init
without releasing the lock it acquired earlier leading to a
deadlock. Hence introduce one more lock iommu_group_mutex
in the arm_smmu_device structure. This way any global modification
to the smr or the s2cr registers are done using the stream_map_mutex
lock which is given up as soon as the modifications are done and
to protect the critical sections which involves the initialization
and the assignment of the iommu groups to the device, use the
iommu_group_mutex lock.

Adding Stack Trace:
[  248.826215] Call trace:
[  248.828769] [<ffffff8008085c58>] __switch_to+0x9c/0xa8
[  248.834081] [<ffffff8008ec82f8>] __schedule+0x7a4/0x8f8
[  248.839460] [<ffffff8008ec84bc>] schedule+0x70/0x8c
[  248.844520] [<ffffff8008ec8530>] schedule_preempt_disabled+0x18/0x28
[  248.851069] [<ffffff8008eca5d0>] __mutex_lock_common+0x550/0xadc
[  248.857251] [<ffffff8008eca070>] __mutex_lock+0x40/0x50
[  248.862674] [<ffffff8008ec95b0>] __mutex_lock_slowpath+0x28/0x34
[  248.868857] [<ffffff8008ec957c>] mutex_lock+0x54/0x60
[  248.874083] [<ffffff8008546808>] arm_smmu_attach_dev+0x1f8/0xcb4
[  248.880314] [<ffffff8008535494>] __iommu_attach_device+0x50/0x114
[  248.886607] [<ffffff8008535290>] iommu_group_add_device+0x268/0x41c
[  248.893072] [<ffffff8008535c98>] iommu_group_get_for_dev+0xc4/0xf0
[  248.899434] [<ffffff8008547c78>] arm_smmu_add_device+0x3e4/0x51c
[  248.905660] [<ffffff800853fcd0>] of_iommu_configure+0x110/0x184
[  248.911767] [<ffffff8008a7a160>] of_dma_configure+0x188/0x288
[  248.917684] [<ffffff80086d0234>] dma_configure+0x64/0x90
[  248.923190] [<ffffff80086b7fa4>] driver_probe_device+0x100/0x430
[  248.929374] [<ffffff80086b85a8>] __driver_attach+0x94/0x118
[  248.935130] [<ffffff80086b5fb4>] bus_for_each_dev+0x7c/0xc4
[  248.940908] [<ffffff80086b8508>] driver_attach+0x2c/0x38
[  248.946372] [<ffffff80086b6740>] bus_add_driver+0x12c/0x234
[  248.952121] [<ffffff80086b96bc>] driver_register+0x90/0xdc
[  248.957764] [<ffffff80086baca8>] __platform_driver_register+0x4c/0x58
[  248.964431] [<ffffff80094f6ed4>] _qcrypto_init+0x18c/0x1c8
[  248.970086] [<ffffff8008083944>] do_one_initcall+0x10c/0x1b0
[  248.975917] [<ffffff80094a0f90>] kernel_init_freeable+0x198/0x238
[  248.982225] [<ffffff8008ec5e10>] kernel_init+0x14/0x104
[  248.987605] [<ffffff8008084bd4>] ret_from_fork+0x10/0x18

Change-Id: Ia8518b0cd6f46ab9dc4c912327d163dff35c7a5b
Signed-off-by: default avatarSwathi Sridhar <swatsrid@codeaurora.org>
Signed-off-by: default avatarVijayanand Jitta <vjitta@codeaurora.org>
parent cf68117b
Loading
Loading
Loading
Loading
+13 −6
Original line number Diff line number Diff line
@@ -460,7 +460,7 @@ struct arm_smmu_device {
	struct arm_smmu_smr		*smrs;
	struct arm_smmu_s2cr		*s2crs;
	struct mutex			stream_map_mutex;

	struct mutex			iommu_group_mutex;
	unsigned long			va_size;
	unsigned long			ipa_size;
	unsigned long			pa_size;
@@ -2308,6 +2308,7 @@ static int arm_smmu_master_alloc_smes(struct device *dev)
	struct iommu_group *group;
	int i, idx, ret;

	mutex_lock(&smmu->iommu_group_mutex);
	mutex_lock(&smmu->stream_map_mutex);
	/* Figure out a viable stream map entry allocation */
	for_each_cfg_sme(fwspec, i, idx) {
@@ -2316,12 +2317,12 @@ static int arm_smmu_master_alloc_smes(struct device *dev)

		if (idx != INVALID_SMENDX) {
			ret = -EEXIST;
			goto out_err;
			goto sme_err;
		}

		ret = arm_smmu_find_sme(smmu, sid, mask);
		if (ret < 0)
			goto out_err;
			goto sme_err;

		idx = ret;
		if (smrs && smmu->s2crs[idx].count == 0) {
@@ -2332,13 +2333,14 @@ static int arm_smmu_master_alloc_smes(struct device *dev)
		smmu->s2crs[idx].count++;
		cfg->smendx[i] = (s16)idx;
	}
	mutex_unlock(&smmu->stream_map_mutex);

	group = iommu_group_get_for_dev(dev);
	if (!group)
		group = ERR_PTR(-ENOMEM);
	if (IS_ERR(group)) {
		ret = PTR_ERR(group);
		goto out_err;
		goto iommu_group_err;
	}
	iommu_group_put(group);

@@ -2346,15 +2348,19 @@ static int arm_smmu_master_alloc_smes(struct device *dev)
	for_each_cfg_sme(fwspec, i, idx)
		smmu->s2crs[idx].group = group;

	mutex_unlock(&smmu->stream_map_mutex);
	mutex_unlock(&smmu->iommu_group_mutex);
	return 0;

out_err:
iommu_group_err:
	mutex_lock(&smmu->stream_map_mutex);

sme_err:
	while (i--) {
		arm_smmu_free_sme(smmu, cfg->smendx[i]);
		cfg->smendx[i] = INVALID_SMENDX;
	}
	mutex_unlock(&smmu->stream_map_mutex);
	mutex_unlock(&smmu->iommu_group_mutex);
	return ret;
}

@@ -4480,6 +4486,7 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)

	smmu->num_mapping_groups = size;
	mutex_init(&smmu->stream_map_mutex);
	mutex_init(&smmu->iommu_group_mutex);

	if (smmu->version < ARM_SMMU_V2 || !(id & ID0_PTFS_NO_AARCH32)) {
		smmu->features |= ARM_SMMU_FEAT_FMT_AARCH32_L;