Commit 6de80d61 authored by Jason Gunthorpe's avatar Jason Gunthorpe Committed by Will Deacon
Browse files

iommu/arm-smmu-v3: Add struct arm_smmu_impl_ops



Mimicing the arm-smmu (v2) driver, introduce a struct arm_smmu_impl_ops to
accommodate impl routines.

Suggested-by: default avatarWill Deacon <will@kernel.org>
Signed-off-by: default avatarJason Gunthorpe <jgg@nvidia.com>
Signed-off-by: default avatarNicolin Chen <nicolinc@nvidia.com>
Link: https://lore.kernel.org/r/8fe9f3805568aabf771fc6706c116459016bf62d.1724970714.git.nicolinc@nvidia.com


Signed-off-by: default avatarWill Deacon <will@kernel.org>
parent 6f3f9ff4
Loading
Loading
Loading
Loading
+50 −1
Original line number Diff line number Diff line
@@ -348,7 +348,12 @@ static int arm_smmu_cmdq_build_cmd(u64 *cmd, struct arm_smmu_cmdq_ent *ent)

static struct arm_smmu_cmdq *arm_smmu_get_cmdq(struct arm_smmu_device *smmu)
{
	return &smmu->cmdq;
	struct arm_smmu_cmdq *cmdq = NULL;

	if (smmu->impl_ops && smmu->impl_ops->get_secondary_cmdq)
		cmdq = smmu->impl_ops->get_secondary_cmdq(smmu);

	return cmdq ?: &smmu->cmdq;
}

static bool arm_smmu_cmdq_needs_busy_polling(struct arm_smmu_device *smmu,
@@ -4052,6 +4057,14 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu)
		return ret;
	}

	if (smmu->impl_ops && smmu->impl_ops->device_reset) {
		ret = smmu->impl_ops->device_reset(smmu);
		if (ret) {
			dev_err(smmu->dev, "failed to reset impl\n");
			return ret;
		}
	}

	return 0;
}

@@ -4466,6 +4479,38 @@ static void arm_smmu_rmr_install_bypass_ste(struct arm_smmu_device *smmu)
	iort_put_rmr_sids(dev_fwnode(smmu->dev), &rmr_list);
}

static void arm_smmu_impl_remove(void *data)
{
	struct arm_smmu_device *smmu = data;

	if (smmu->impl_ops && smmu->impl_ops->device_remove)
		smmu->impl_ops->device_remove(smmu);
}

/*
 * Probe all the compiled in implementations. Each one checks to see if it
 * matches this HW and if so returns a devm_krealloc'd arm_smmu_device which
 * replaces the callers. Otherwise the original is returned or ERR_PTR.
 */
static struct arm_smmu_device *arm_smmu_impl_probe(struct arm_smmu_device *smmu)
{
	struct arm_smmu_device *new_smmu = ERR_PTR(-ENODEV);
	int ret;

	/* Add impl probe */

	if (new_smmu == ERR_PTR(-ENODEV))
		return smmu;
	if (IS_ERR(new_smmu))
		return new_smmu;

	ret = devm_add_action_or_reset(new_smmu->dev, arm_smmu_impl_remove,
				       new_smmu);
	if (ret)
		return ERR_PTR(ret);
	return new_smmu;
}

static int arm_smmu_device_probe(struct platform_device *pdev)
{
	int irq, ret;
@@ -4487,6 +4532,10 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
	if (ret)
		return ret;

	smmu = arm_smmu_impl_probe(smmu);
	if (IS_ERR(smmu))
		return PTR_ERR(smmu);

	/* Base address */
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res)
+10 −0
Original line number Diff line number Diff line
@@ -14,6 +14,8 @@
#include <linux/mmzone.h>
#include <linux/sizes.h>

struct arm_smmu_device;

/* MMIO registers */
#define ARM_SMMU_IDR0			0x0
#define IDR0_ST_LVL			GENMASK(28, 27)
@@ -630,9 +632,17 @@ struct arm_smmu_strtab_cfg {
	u32				strtab_base_cfg;
};

struct arm_smmu_impl_ops {
	int (*device_reset)(struct arm_smmu_device *smmu);
	void (*device_remove)(struct arm_smmu_device *smmu);
	struct arm_smmu_cmdq *(*get_secondary_cmdq)(struct arm_smmu_device *smmu);
};

/* An SMMUv3 instance */
struct arm_smmu_device {
	struct device			*dev;
	const struct arm_smmu_impl_ops	*impl_ops;

	void __iomem			*base;
	void __iomem			*page1;