mirror of
https://github.com/torvalds/linux.git
synced 2026-05-27 08:33:17 +02:00
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: Will Deacon <will@kernel.org> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com> Signed-off-by: Nicolin Chen <nicolinc@nvidia.com> Link: https://lore.kernel.org/r/8fe9f3805568aabf771fc6706c116459016bf62d.1724970714.git.nicolinc@nvidia.com Signed-off-by: Will Deacon <will@kernel.org>
This commit is contained in:
parent
6f3f9ff43d
commit
6de80d6192
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user