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

Commit 0964a681 authored by Isaac J. Manjarres's avatar Isaac J. Manjarres
Browse files

iommu/arm-smmu: Add implementation specific device group matching



Certain SMMU implementations depend on implementation specific
settings to ensure that translations for a group of SMMU masters
work properly, so add a function to determine if a master belongs
in a particular IOMMU group based on implementation defined
settings.

Also, wire up the QSMMUV500 implementation of this hook, leaving
the arm_smmu_arch_ops structure completely unused. Since it has
been superseded by the implementation framework, remove the
remaining support for it.

Change-Id: I53b1b014be187757c6e48e57f23cc9732103f890
Signed-off-by: default avatarIsaac J. Manjarres <isaacm@codeaurora.org>
parent 84af7c67
Loading
Loading
Loading
Loading
+1 −4
Original line number Diff line number Diff line
@@ -850,16 +850,13 @@ static int qsmmuv500_cfg_probe(struct arm_smmu_device *smmu)
	return 0;
}

struct arm_smmu_arch_ops qsmmuv500_arch_ops = {
	.device_group = qsmmuv500_device_group,
};

static const struct arm_smmu_impl qsmmuv500_impl = {
	.cfg_probe = qsmmuv500_cfg_probe,
	.init_context_bank = qsmmuv500_init_cb,
	.iova_to_phys_hard = qsmmuv500_iova_to_phys_hard,
	.tlb_sync_timeout = qsmmuv500_tlb_sync_timeout,
	.device_remove = qsmmuv500_device_remove,
	.device_group = qsmmuv500_device_group,
};

struct arm_smmu_device *qsmmuv500_impl_init(struct arm_smmu_device *smmu)
+12 −31
Original line number Diff line number Diff line
@@ -350,19 +350,6 @@ static void arm_smmu_interrupt_selftest(struct arm_smmu_device *smmu)
}
#endif

static int arm_smmu_arch_device_group(struct device *dev,
					struct iommu_group *group)
{
	struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
	struct arm_smmu_device *smmu = fwspec_smmu(fwspec);

	if (!smmu->arch_ops)
		return 0;
	if (!smmu->arch_ops->device_group)
		return 0;
	return smmu->arch_ops->device_group(dev, group);
}

static void arm_smmu_arch_write_sync(struct arm_smmu_device *smmu)
{
	u32 id;
@@ -3330,7 +3317,8 @@ static struct iommu_group *arm_smmu_device_group(struct device *dev)
			return NULL;
	}

	if (arm_smmu_arch_device_group(dev, group)) {
	if (smmu->impl && smmu->impl->device_group &&
	    smmu->impl->device_group(dev, group)) {
		iommu_group_put(group);
		return ERR_PTR(-EINVAL);
	}
@@ -4461,24 +4449,18 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
struct arm_smmu_match_data {
	enum arm_smmu_arch_version version;
	enum arm_smmu_implementation model;
	struct arm_smmu_arch_ops *arch_ops;
};

#define ARM_SMMU_MATCH_DATA(name, ver, imp, ops)	\
static struct arm_smmu_match_data name = {		\
.version = ver,						\
.model = imp,						\
.arch_ops = ops,					\
}							\
#define ARM_SMMU_MATCH_DATA(name, ver, imp)	\
static const struct arm_smmu_match_data name = { .version = ver, .model = imp }

ARM_SMMU_MATCH_DATA(smmu_generic_v1, ARM_SMMU_V1, GENERIC_SMMU, NULL);
ARM_SMMU_MATCH_DATA(smmu_generic_v2, ARM_SMMU_V2, GENERIC_SMMU, NULL);
ARM_SMMU_MATCH_DATA(arm_mmu401, ARM_SMMU_V1_64K, GENERIC_SMMU, NULL);
ARM_SMMU_MATCH_DATA(arm_mmu500, ARM_SMMU_V2, ARM_MMU500, NULL);
ARM_SMMU_MATCH_DATA(cavium_smmuv2, ARM_SMMU_V2, CAVIUM_SMMUV2, NULL);
ARM_SMMU_MATCH_DATA(qcom_smmuv500, ARM_SMMU_V2, QCOM_SMMUV500,
		    &qsmmuv500_arch_ops);
ARM_SMMU_MATCH_DATA(qcom_smmuv2, ARM_SMMU_V2, QCOM_SMMUV2, NULL);
ARM_SMMU_MATCH_DATA(smmu_generic_v1, ARM_SMMU_V1, GENERIC_SMMU);
ARM_SMMU_MATCH_DATA(smmu_generic_v2, ARM_SMMU_V2, GENERIC_SMMU);
ARM_SMMU_MATCH_DATA(arm_mmu401, ARM_SMMU_V1_64K, GENERIC_SMMU);
ARM_SMMU_MATCH_DATA(arm_mmu500, ARM_SMMU_V2, ARM_MMU500);
ARM_SMMU_MATCH_DATA(cavium_smmuv2, ARM_SMMU_V2, CAVIUM_SMMUV2);
ARM_SMMU_MATCH_DATA(qcom_smmuv500, ARM_SMMU_V2, QCOM_SMMUV500);
ARM_SMMU_MATCH_DATA(qcom_smmuv2, ARM_SMMU_V2, QCOM_SMMUV2);

static const struct of_device_id arm_smmu_of_match[] = {
	{ .compatible = "arm,smmu-v1", .data = &smmu_generic_v1 },
@@ -4637,7 +4619,6 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
	data = of_device_get_match_data(dev);
	smmu->version = data->version;
	smmu->model = data->model;
	smmu->arch_ops = data->arch_ops;

	if (of_dma_is_coherent(dev->of_node))
		smmu->features |= ARM_SMMU_FEAT_COHERENT_WALK;
+1 −11
Original line number Diff line number Diff line
@@ -398,7 +398,6 @@ struct arm_smmu_device {
	struct mutex			idr_mutex;
	struct idr			asid_idr;

	struct arm_smmu_arch_ops	*arch_ops;
	unsigned long			sync_timed_out;
};

@@ -509,6 +508,7 @@ struct arm_smmu_impl {
					 unsigned long trans_flags);
	void (*tlb_sync_timeout)(struct arm_smmu_device *smmu);
	void (*device_remove)(struct arm_smmu_device *smmu);
	int (*device_group)(struct device *dev, struct iommu_group *group);
};

static inline void __iomem *arm_smmu_page(struct arm_smmu_device *smmu, int n)
@@ -572,14 +572,6 @@ static inline void arm_smmu_writeq(struct arm_smmu_device *smmu, int page,
#define arm_smmu_cb_writeq(s, n, o, v)	\
	arm_smmu_writeq((s), ARM_SMMU_CB((s), (n)), (o), (v))

/*
 * device_group()
 * Hook for checking whether a device is compatible with a said group.
 */
struct arm_smmu_arch_ops {
	int (*device_group)(struct device *dev, struct iommu_group *group);
};

struct arm_smmu_device *arm_smmu_impl_init(struct arm_smmu_device *smmu);
struct arm_smmu_device *qcom_smmu_impl_init(struct arm_smmu_device *smmu);
struct arm_smmu_device *qsmmuv500_impl_init(struct arm_smmu_device *smmu);
@@ -590,8 +582,6 @@ int arm_smmu_power_on(struct arm_smmu_power_resources *pwr);
void arm_smmu_power_off(struct arm_smmu_device *smmu,
			struct arm_smmu_power_resources *pwr);

extern struct arm_smmu_arch_ops qsmmuv500_arch_ops;

/* Misc. constants */
#define TBUID_SHIFT                     10
#define ARM_MMU500_ACR_CACHE_LOCK	(1 << 26)