From: Thierry Reding <thierry.reding@gmail.com>
To: Krishna Reddy <vdumpa@nvidia.com>
Cc: treding@nvidia.com, bhuntsman@nvidia.com, robin.murphy@arm.com,
linux-kernel@vger.kernel.org, iommu@lists.linux-foundation.org,
mperttunen@nvidia.com, talho@nvidia.com, snikam@nvidia.com,
nicolinc@nvidia.com, linux-tegra@vger.kernel.org,
yhsu@nvidia.com, praithatha@nvidia.com, will@kernel.org,
linux-arm-kernel@lists.infradead.org, bbiswas@nvidia.com
Subject: Re: [PATCH v6 3/4] iommu/arm-smmu: Add global/context fault implementation hooks
Date: Tue, 23 Jun 2020 10:36:43 +0200 [thread overview]
Message-ID: <20200623083643.GB4098287@ulmo> (raw)
In-Reply-To: <20200604234414.21912-4-vdumpa@nvidia.com>
[-- Attachment #1.1: Type: text/plain, Size: 6432 bytes --]
On Thu, Jun 04, 2020 at 04:44:13PM -0700, Krishna Reddy wrote:
> Add global/context fault hooks to allow NVIDIA SMMU implementation
> handle faults across multiple SMMUs.
>
> Signed-off-by: Krishna Reddy <vdumpa@nvidia.com>
> ---
> drivers/iommu/arm-smmu-nvidia.c | 100 ++++++++++++++++++++++++++++++++
> drivers/iommu/arm-smmu.c | 11 +++-
> drivers/iommu/arm-smmu.h | 3 +
> 3 files changed, 112 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/iommu/arm-smmu-nvidia.c b/drivers/iommu/arm-smmu-nvidia.c
> index dafc293a45217..5999b6a770992 100644
> --- a/drivers/iommu/arm-smmu-nvidia.c
> +++ b/drivers/iommu/arm-smmu-nvidia.c
> @@ -117,6 +117,104 @@ static int nsmmu_reset(struct arm_smmu_device *smmu)
> return 0;
> }
>
> +static struct arm_smmu_domain *to_smmu_domain(struct iommu_domain *dom)
> +{
> + return container_of(dom, struct arm_smmu_domain, domain);
> +}
> +
> +static irqreturn_t nsmmu_global_fault_inst(int irq,
> + struct arm_smmu_device *smmu,
> + int inst)
> +{
> + u32 gfsr, gfsynr0, gfsynr1, gfsynr2;
> +
> + gfsr = readl_relaxed(nsmmu_page(smmu, inst, 0) + ARM_SMMU_GR0_sGFSR);
> + gfsynr0 = readl_relaxed(nsmmu_page(smmu, inst, 0) +
> + ARM_SMMU_GR0_sGFSYNR0);
> + gfsynr1 = readl_relaxed(nsmmu_page(smmu, inst, 0) +
> + ARM_SMMU_GR0_sGFSYNR1);
> + gfsynr2 = readl_relaxed(nsmmu_page(smmu, inst, 0) +
> + ARM_SMMU_GR0_sGFSYNR2);
> +
> + if (!gfsr)
> + return IRQ_NONE;
> +
> + dev_err_ratelimited(smmu->dev,
> + "Unexpected global fault, this could be serious\n");
> + dev_err_ratelimited(smmu->dev,
> + "\tGFSR 0x%08x, GFSYNR0 0x%08x, GFSYNR1 0x%08x, GFSYNR2 0x%08x\n",
> + gfsr, gfsynr0, gfsynr1, gfsynr2);
> +
> + writel_relaxed(gfsr, nsmmu_page(smmu, inst, 0) + ARM_SMMU_GR0_sGFSR);
> + return IRQ_HANDLED;
> +}
> +
> +static irqreturn_t nsmmu_global_fault(int irq, void *dev)
> +{
> + int inst;
> + irqreturn_t irq_ret = IRQ_NONE;
> + struct arm_smmu_device *smmu = dev;
> +
> + for (inst = 0; inst < to_nvidia_smmu(smmu)->num_inst; inst++) {
> + irq_ret = nsmmu_global_fault_inst(irq, smmu, inst);
> + if (irq_ret == IRQ_HANDLED)
> + return irq_ret;
> + }
> +
> + return irq_ret;
> +}
> +
> +static irqreturn_t nsmmu_context_fault_bank(int irq,
> + struct arm_smmu_device *smmu,
> + int idx, int inst)
> +{
> + u32 fsr, fsynr, cbfrsynra;
> + unsigned long iova;
> +
> + fsr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSR);
> + if (!(fsr & ARM_SMMU_FSR_FAULT))
> + return IRQ_NONE;
> +
> + fsynr = readl_relaxed(nsmmu_page(smmu, inst, smmu->numpage + idx) +
> + ARM_SMMU_CB_FSYNR0);
> + iova = readq_relaxed(nsmmu_page(smmu, inst, smmu->numpage + idx) +
> + ARM_SMMU_CB_FAR);
> + cbfrsynra = readl_relaxed(nsmmu_page(smmu, inst, 1) +
> + ARM_SMMU_GR1_CBFRSYNRA(idx));
> +
> + dev_err_ratelimited(smmu->dev,
> + "Unhandled context fault: fsr=0x%x, iova=0x%08lx, fsynr=0x%x, cbfrsynra=0x%x, cb=%d\n",
> + fsr, iova, fsynr, cbfrsynra, idx);
> +
> + writel_relaxed(fsr, nsmmu_page(smmu, inst, smmu->numpage + idx) +
> + ARM_SMMU_CB_FSR);
> + return IRQ_HANDLED;
> +}
> +
> +static irqreturn_t nsmmu_context_fault(int irq, void *dev)
> +{
> + int inst, idx;
> + irqreturn_t irq_ret = IRQ_NONE;
> + struct iommu_domain *domain = dev;
> + struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
> + struct arm_smmu_device *smmu = smmu_domain->smmu;
> +
> + for (inst = 0; inst < to_nvidia_smmu(smmu)->num_inst; inst++) {
> + /* Interrupt line shared between all context faults.
> + * Check for faults across all contexts.
> + */
> + for (idx = 0; idx < smmu->num_context_banks; idx++) {
> + irq_ret = nsmmu_context_fault_bank(irq, smmu,
> + idx, inst);
> +
> + if (irq_ret == IRQ_HANDLED)
> + return irq_ret;
> + }
> + }
> +
> + return irq_ret;
> +}
> +
> static const struct arm_smmu_impl nvidia_smmu_impl = {
> .read_reg = nsmmu_read_reg,
> .write_reg = nsmmu_write_reg,
> @@ -124,6 +222,8 @@ static const struct arm_smmu_impl nvidia_smmu_impl = {
> .write_reg64 = nsmmu_write_reg64,
> .reset = nsmmu_reset,
> .tlb_sync = nsmmu_tlb_sync,
> + .global_fault = nsmmu_global_fault,
> + .context_fault = nsmmu_context_fault,
> };
>
> struct arm_smmu_device *nvidia_smmu_impl_init(struct arm_smmu_device *smmu)
> diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
> index 243bc4cb2705b..d720e1e191176 100644
> --- a/drivers/iommu/arm-smmu.c
> +++ b/drivers/iommu/arm-smmu.c
> @@ -673,6 +673,7 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
> enum io_pgtable_fmt fmt;
> struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
> struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
> + irqreturn_t (*context_fault)(int irq, void *dev);
>
> mutex_lock(&smmu_domain->init_mutex);
> if (smmu_domain->smmu)
> @@ -835,7 +836,9 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
> * handler seeing a half-initialised domain state.
> */
> irq = smmu->irqs[smmu->num_global_irqs + cfg->irptndx];
> - ret = devm_request_irq(smmu->dev, irq, arm_smmu_context_fault,
> + context_fault = (smmu->impl && smmu->impl->context_fault) ?
> + smmu->impl->context_fault : arm_smmu_context_fault;
A simpler way might have been to assign arm_smmu_context_fault to all
implementations. That way we wouldn't have to perform this check here
and instead just always using smmu->impl->context_fault.
> + ret = devm_request_irq(smmu->dev, irq, context_fault,
> IRQF_SHARED, "arm-smmu-context-fault", domain);
> if (ret < 0) {
> dev_err(smmu->dev, "failed to request context IRQ %d (%u)\n",
> @@ -2107,6 +2110,7 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
> struct arm_smmu_device *smmu;
> struct device *dev = &pdev->dev;
> int num_irqs, i, err;
> + irqreturn_t (*global_fault)(int irq, void *dev);
>
> smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL);
> if (!smmu) {
> @@ -2193,9 +2197,12 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
> smmu->num_context_irqs = smmu->num_context_banks;
> }
>
> + global_fault = (smmu->impl && smmu->impl->global_fault) ?
> + smmu->impl->global_fault : arm_smmu_global_fault;
> +
Same as above.
Thierry
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
[-- Attachment #2: Type: text/plain, Size: 156 bytes --]
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu
WARNING: multiple messages have this Message-ID (diff)
From: Thierry Reding <thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
To: Krishna Reddy <vdumpa-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
Cc: snikam-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org,
mperttunen-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org,
bhuntsman-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org,
will-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org,
joro-zLv9SwRftAIdnm+yROfE0A@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
praithatha-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org,
talho-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org,
iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org,
nicolinc-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org,
linux-tegra-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
yhsu-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org,
treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org,
robin.murphy-5wv7dgnIgG8@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
bbiswas-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org
Subject: Re: [PATCH v6 3/4] iommu/arm-smmu: Add global/context fault implementation hooks
Date: Tue, 23 Jun 2020 10:36:43 +0200 [thread overview]
Message-ID: <20200623083643.GB4098287@ulmo> (raw)
In-Reply-To: <20200604234414.21912-4-vdumpa-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 6461 bytes --]
On Thu, Jun 04, 2020 at 04:44:13PM -0700, Krishna Reddy wrote:
> Add global/context fault hooks to allow NVIDIA SMMU implementation
> handle faults across multiple SMMUs.
>
> Signed-off-by: Krishna Reddy <vdumpa-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
> ---
> drivers/iommu/arm-smmu-nvidia.c | 100 ++++++++++++++++++++++++++++++++
> drivers/iommu/arm-smmu.c | 11 +++-
> drivers/iommu/arm-smmu.h | 3 +
> 3 files changed, 112 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/iommu/arm-smmu-nvidia.c b/drivers/iommu/arm-smmu-nvidia.c
> index dafc293a45217..5999b6a770992 100644
> --- a/drivers/iommu/arm-smmu-nvidia.c
> +++ b/drivers/iommu/arm-smmu-nvidia.c
> @@ -117,6 +117,104 @@ static int nsmmu_reset(struct arm_smmu_device *smmu)
> return 0;
> }
>
> +static struct arm_smmu_domain *to_smmu_domain(struct iommu_domain *dom)
> +{
> + return container_of(dom, struct arm_smmu_domain, domain);
> +}
> +
> +static irqreturn_t nsmmu_global_fault_inst(int irq,
> + struct arm_smmu_device *smmu,
> + int inst)
> +{
> + u32 gfsr, gfsynr0, gfsynr1, gfsynr2;
> +
> + gfsr = readl_relaxed(nsmmu_page(smmu, inst, 0) + ARM_SMMU_GR0_sGFSR);
> + gfsynr0 = readl_relaxed(nsmmu_page(smmu, inst, 0) +
> + ARM_SMMU_GR0_sGFSYNR0);
> + gfsynr1 = readl_relaxed(nsmmu_page(smmu, inst, 0) +
> + ARM_SMMU_GR0_sGFSYNR1);
> + gfsynr2 = readl_relaxed(nsmmu_page(smmu, inst, 0) +
> + ARM_SMMU_GR0_sGFSYNR2);
> +
> + if (!gfsr)
> + return IRQ_NONE;
> +
> + dev_err_ratelimited(smmu->dev,
> + "Unexpected global fault, this could be serious\n");
> + dev_err_ratelimited(smmu->dev,
> + "\tGFSR 0x%08x, GFSYNR0 0x%08x, GFSYNR1 0x%08x, GFSYNR2 0x%08x\n",
> + gfsr, gfsynr0, gfsynr1, gfsynr2);
> +
> + writel_relaxed(gfsr, nsmmu_page(smmu, inst, 0) + ARM_SMMU_GR0_sGFSR);
> + return IRQ_HANDLED;
> +}
> +
> +static irqreturn_t nsmmu_global_fault(int irq, void *dev)
> +{
> + int inst;
> + irqreturn_t irq_ret = IRQ_NONE;
> + struct arm_smmu_device *smmu = dev;
> +
> + for (inst = 0; inst < to_nvidia_smmu(smmu)->num_inst; inst++) {
> + irq_ret = nsmmu_global_fault_inst(irq, smmu, inst);
> + if (irq_ret == IRQ_HANDLED)
> + return irq_ret;
> + }
> +
> + return irq_ret;
> +}
> +
> +static irqreturn_t nsmmu_context_fault_bank(int irq,
> + struct arm_smmu_device *smmu,
> + int idx, int inst)
> +{
> + u32 fsr, fsynr, cbfrsynra;
> + unsigned long iova;
> +
> + fsr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSR);
> + if (!(fsr & ARM_SMMU_FSR_FAULT))
> + return IRQ_NONE;
> +
> + fsynr = readl_relaxed(nsmmu_page(smmu, inst, smmu->numpage + idx) +
> + ARM_SMMU_CB_FSYNR0);
> + iova = readq_relaxed(nsmmu_page(smmu, inst, smmu->numpage + idx) +
> + ARM_SMMU_CB_FAR);
> + cbfrsynra = readl_relaxed(nsmmu_page(smmu, inst, 1) +
> + ARM_SMMU_GR1_CBFRSYNRA(idx));
> +
> + dev_err_ratelimited(smmu->dev,
> + "Unhandled context fault: fsr=0x%x, iova=0x%08lx, fsynr=0x%x, cbfrsynra=0x%x, cb=%d\n",
> + fsr, iova, fsynr, cbfrsynra, idx);
> +
> + writel_relaxed(fsr, nsmmu_page(smmu, inst, smmu->numpage + idx) +
> + ARM_SMMU_CB_FSR);
> + return IRQ_HANDLED;
> +}
> +
> +static irqreturn_t nsmmu_context_fault(int irq, void *dev)
> +{
> + int inst, idx;
> + irqreturn_t irq_ret = IRQ_NONE;
> + struct iommu_domain *domain = dev;
> + struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
> + struct arm_smmu_device *smmu = smmu_domain->smmu;
> +
> + for (inst = 0; inst < to_nvidia_smmu(smmu)->num_inst; inst++) {
> + /* Interrupt line shared between all context faults.
> + * Check for faults across all contexts.
> + */
> + for (idx = 0; idx < smmu->num_context_banks; idx++) {
> + irq_ret = nsmmu_context_fault_bank(irq, smmu,
> + idx, inst);
> +
> + if (irq_ret == IRQ_HANDLED)
> + return irq_ret;
> + }
> + }
> +
> + return irq_ret;
> +}
> +
> static const struct arm_smmu_impl nvidia_smmu_impl = {
> .read_reg = nsmmu_read_reg,
> .write_reg = nsmmu_write_reg,
> @@ -124,6 +222,8 @@ static const struct arm_smmu_impl nvidia_smmu_impl = {
> .write_reg64 = nsmmu_write_reg64,
> .reset = nsmmu_reset,
> .tlb_sync = nsmmu_tlb_sync,
> + .global_fault = nsmmu_global_fault,
> + .context_fault = nsmmu_context_fault,
> };
>
> struct arm_smmu_device *nvidia_smmu_impl_init(struct arm_smmu_device *smmu)
> diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
> index 243bc4cb2705b..d720e1e191176 100644
> --- a/drivers/iommu/arm-smmu.c
> +++ b/drivers/iommu/arm-smmu.c
> @@ -673,6 +673,7 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
> enum io_pgtable_fmt fmt;
> struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
> struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
> + irqreturn_t (*context_fault)(int irq, void *dev);
>
> mutex_lock(&smmu_domain->init_mutex);
> if (smmu_domain->smmu)
> @@ -835,7 +836,9 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
> * handler seeing a half-initialised domain state.
> */
> irq = smmu->irqs[smmu->num_global_irqs + cfg->irptndx];
> - ret = devm_request_irq(smmu->dev, irq, arm_smmu_context_fault,
> + context_fault = (smmu->impl && smmu->impl->context_fault) ?
> + smmu->impl->context_fault : arm_smmu_context_fault;
A simpler way might have been to assign arm_smmu_context_fault to all
implementations. That way we wouldn't have to perform this check here
and instead just always using smmu->impl->context_fault.
> + ret = devm_request_irq(smmu->dev, irq, context_fault,
> IRQF_SHARED, "arm-smmu-context-fault", domain);
> if (ret < 0) {
> dev_err(smmu->dev, "failed to request context IRQ %d (%u)\n",
> @@ -2107,6 +2110,7 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
> struct arm_smmu_device *smmu;
> struct device *dev = &pdev->dev;
> int num_irqs, i, err;
> + irqreturn_t (*global_fault)(int irq, void *dev);
>
> smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL);
> if (!smmu) {
> @@ -2193,9 +2197,12 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
> smmu->num_context_irqs = smmu->num_context_banks;
> }
>
> + global_fault = (smmu->impl && smmu->impl->global_fault) ?
> + smmu->impl->global_fault : arm_smmu_global_fault;
> +
Same as above.
Thierry
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
WARNING: multiple messages have this Message-ID (diff)
From: Thierry Reding <thierry.reding@gmail.com>
To: Krishna Reddy <vdumpa@nvidia.com>
Cc: snikam@nvidia.com, mperttunen@nvidia.com, bhuntsman@nvidia.com,
will@kernel.org, joro@8bytes.org, linux-kernel@vger.kernel.org,
praithatha@nvidia.com, talho@nvidia.com,
iommu@lists.linux-foundation.org, nicolinc@nvidia.com,
linux-tegra@vger.kernel.org, yhsu@nvidia.com, treding@nvidia.com,
robin.murphy@arm.com, linux-arm-kernel@lists.infradead.org,
bbiswas@nvidia.com
Subject: Re: [PATCH v6 3/4] iommu/arm-smmu: Add global/context fault implementation hooks
Date: Tue, 23 Jun 2020 10:36:43 +0200 [thread overview]
Message-ID: <20200623083643.GB4098287@ulmo> (raw)
In-Reply-To: <20200604234414.21912-4-vdumpa@nvidia.com>
[-- Attachment #1: Type: text/plain, Size: 6432 bytes --]
On Thu, Jun 04, 2020 at 04:44:13PM -0700, Krishna Reddy wrote:
> Add global/context fault hooks to allow NVIDIA SMMU implementation
> handle faults across multiple SMMUs.
>
> Signed-off-by: Krishna Reddy <vdumpa@nvidia.com>
> ---
> drivers/iommu/arm-smmu-nvidia.c | 100 ++++++++++++++++++++++++++++++++
> drivers/iommu/arm-smmu.c | 11 +++-
> drivers/iommu/arm-smmu.h | 3 +
> 3 files changed, 112 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/iommu/arm-smmu-nvidia.c b/drivers/iommu/arm-smmu-nvidia.c
> index dafc293a45217..5999b6a770992 100644
> --- a/drivers/iommu/arm-smmu-nvidia.c
> +++ b/drivers/iommu/arm-smmu-nvidia.c
> @@ -117,6 +117,104 @@ static int nsmmu_reset(struct arm_smmu_device *smmu)
> return 0;
> }
>
> +static struct arm_smmu_domain *to_smmu_domain(struct iommu_domain *dom)
> +{
> + return container_of(dom, struct arm_smmu_domain, domain);
> +}
> +
> +static irqreturn_t nsmmu_global_fault_inst(int irq,
> + struct arm_smmu_device *smmu,
> + int inst)
> +{
> + u32 gfsr, gfsynr0, gfsynr1, gfsynr2;
> +
> + gfsr = readl_relaxed(nsmmu_page(smmu, inst, 0) + ARM_SMMU_GR0_sGFSR);
> + gfsynr0 = readl_relaxed(nsmmu_page(smmu, inst, 0) +
> + ARM_SMMU_GR0_sGFSYNR0);
> + gfsynr1 = readl_relaxed(nsmmu_page(smmu, inst, 0) +
> + ARM_SMMU_GR0_sGFSYNR1);
> + gfsynr2 = readl_relaxed(nsmmu_page(smmu, inst, 0) +
> + ARM_SMMU_GR0_sGFSYNR2);
> +
> + if (!gfsr)
> + return IRQ_NONE;
> +
> + dev_err_ratelimited(smmu->dev,
> + "Unexpected global fault, this could be serious\n");
> + dev_err_ratelimited(smmu->dev,
> + "\tGFSR 0x%08x, GFSYNR0 0x%08x, GFSYNR1 0x%08x, GFSYNR2 0x%08x\n",
> + gfsr, gfsynr0, gfsynr1, gfsynr2);
> +
> + writel_relaxed(gfsr, nsmmu_page(smmu, inst, 0) + ARM_SMMU_GR0_sGFSR);
> + return IRQ_HANDLED;
> +}
> +
> +static irqreturn_t nsmmu_global_fault(int irq, void *dev)
> +{
> + int inst;
> + irqreturn_t irq_ret = IRQ_NONE;
> + struct arm_smmu_device *smmu = dev;
> +
> + for (inst = 0; inst < to_nvidia_smmu(smmu)->num_inst; inst++) {
> + irq_ret = nsmmu_global_fault_inst(irq, smmu, inst);
> + if (irq_ret == IRQ_HANDLED)
> + return irq_ret;
> + }
> +
> + return irq_ret;
> +}
> +
> +static irqreturn_t nsmmu_context_fault_bank(int irq,
> + struct arm_smmu_device *smmu,
> + int idx, int inst)
> +{
> + u32 fsr, fsynr, cbfrsynra;
> + unsigned long iova;
> +
> + fsr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSR);
> + if (!(fsr & ARM_SMMU_FSR_FAULT))
> + return IRQ_NONE;
> +
> + fsynr = readl_relaxed(nsmmu_page(smmu, inst, smmu->numpage + idx) +
> + ARM_SMMU_CB_FSYNR0);
> + iova = readq_relaxed(nsmmu_page(smmu, inst, smmu->numpage + idx) +
> + ARM_SMMU_CB_FAR);
> + cbfrsynra = readl_relaxed(nsmmu_page(smmu, inst, 1) +
> + ARM_SMMU_GR1_CBFRSYNRA(idx));
> +
> + dev_err_ratelimited(smmu->dev,
> + "Unhandled context fault: fsr=0x%x, iova=0x%08lx, fsynr=0x%x, cbfrsynra=0x%x, cb=%d\n",
> + fsr, iova, fsynr, cbfrsynra, idx);
> +
> + writel_relaxed(fsr, nsmmu_page(smmu, inst, smmu->numpage + idx) +
> + ARM_SMMU_CB_FSR);
> + return IRQ_HANDLED;
> +}
> +
> +static irqreturn_t nsmmu_context_fault(int irq, void *dev)
> +{
> + int inst, idx;
> + irqreturn_t irq_ret = IRQ_NONE;
> + struct iommu_domain *domain = dev;
> + struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
> + struct arm_smmu_device *smmu = smmu_domain->smmu;
> +
> + for (inst = 0; inst < to_nvidia_smmu(smmu)->num_inst; inst++) {
> + /* Interrupt line shared between all context faults.
> + * Check for faults across all contexts.
> + */
> + for (idx = 0; idx < smmu->num_context_banks; idx++) {
> + irq_ret = nsmmu_context_fault_bank(irq, smmu,
> + idx, inst);
> +
> + if (irq_ret == IRQ_HANDLED)
> + return irq_ret;
> + }
> + }
> +
> + return irq_ret;
> +}
> +
> static const struct arm_smmu_impl nvidia_smmu_impl = {
> .read_reg = nsmmu_read_reg,
> .write_reg = nsmmu_write_reg,
> @@ -124,6 +222,8 @@ static const struct arm_smmu_impl nvidia_smmu_impl = {
> .write_reg64 = nsmmu_write_reg64,
> .reset = nsmmu_reset,
> .tlb_sync = nsmmu_tlb_sync,
> + .global_fault = nsmmu_global_fault,
> + .context_fault = nsmmu_context_fault,
> };
>
> struct arm_smmu_device *nvidia_smmu_impl_init(struct arm_smmu_device *smmu)
> diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
> index 243bc4cb2705b..d720e1e191176 100644
> --- a/drivers/iommu/arm-smmu.c
> +++ b/drivers/iommu/arm-smmu.c
> @@ -673,6 +673,7 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
> enum io_pgtable_fmt fmt;
> struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
> struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
> + irqreturn_t (*context_fault)(int irq, void *dev);
>
> mutex_lock(&smmu_domain->init_mutex);
> if (smmu_domain->smmu)
> @@ -835,7 +836,9 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
> * handler seeing a half-initialised domain state.
> */
> irq = smmu->irqs[smmu->num_global_irqs + cfg->irptndx];
> - ret = devm_request_irq(smmu->dev, irq, arm_smmu_context_fault,
> + context_fault = (smmu->impl && smmu->impl->context_fault) ?
> + smmu->impl->context_fault : arm_smmu_context_fault;
A simpler way might have been to assign arm_smmu_context_fault to all
implementations. That way we wouldn't have to perform this check here
and instead just always using smmu->impl->context_fault.
> + ret = devm_request_irq(smmu->dev, irq, context_fault,
> IRQF_SHARED, "arm-smmu-context-fault", domain);
> if (ret < 0) {
> dev_err(smmu->dev, "failed to request context IRQ %d (%u)\n",
> @@ -2107,6 +2110,7 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
> struct arm_smmu_device *smmu;
> struct device *dev = &pdev->dev;
> int num_irqs, i, err;
> + irqreturn_t (*global_fault)(int irq, void *dev);
>
> smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL);
> if (!smmu) {
> @@ -2193,9 +2197,12 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
> smmu->num_context_irqs = smmu->num_context_banks;
> }
>
> + global_fault = (smmu->impl && smmu->impl->global_fault) ?
> + smmu->impl->global_fault : arm_smmu_global_fault;
> +
Same as above.
Thierry
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
next prev parent reply other threads:[~2020-06-23 8:36 UTC|newest]
Thread overview: 52+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-06-04 23:44 [PATCH v6 0/4] Nvidia Arm SMMUv2 Implementation Krishna Reddy
2020-06-04 23:44 ` Krishna Reddy
2020-06-04 23:44 ` Krishna Reddy
2020-06-04 23:44 ` Krishna Reddy
2020-06-04 23:44 ` [PATCH v6 1/4] iommu/arm-smmu: add NVIDIA implementation for dual ARM MMU-500 usage Krishna Reddy
2020-06-04 23:44 ` Krishna Reddy
2020-06-04 23:44 ` Krishna Reddy
2020-06-04 23:44 ` Krishna Reddy
2020-06-23 10:29 ` Thierry Reding
2020-06-23 10:29 ` Thierry Reding
2020-06-23 10:29 ` Thierry Reding
2020-06-23 11:16 ` Robin Murphy
2020-06-23 11:16 ` Robin Murphy
2020-06-23 11:16 ` Robin Murphy
2020-06-23 12:47 ` Thierry Reding
2020-06-23 12:47 ` Thierry Reding
2020-06-23 12:47 ` Thierry Reding
2020-06-25 23:13 ` Krishna Reddy
2020-06-25 23:13 ` Krishna Reddy
2020-06-25 23:13 ` Krishna Reddy
2020-06-25 23:13 ` Krishna Reddy
2020-06-04 23:44 ` [PATCH v6 2/4] dt-bindings: arm-smmu: Add binding for Tegra194 SMMU Krishna Reddy
2020-06-04 23:44 ` Krishna Reddy
2020-06-04 23:44 ` Krishna Reddy
2020-06-04 23:44 ` Krishna Reddy
2020-06-23 8:38 ` Thierry Reding
2020-06-23 8:38 ` Thierry Reding
2020-06-23 8:38 ` Thierry Reding
2020-06-25 22:32 ` Krishna Reddy
2020-06-25 22:32 ` Krishna Reddy
2020-06-25 22:32 ` Krishna Reddy
2020-06-25 22:32 ` Krishna Reddy
2020-06-04 23:44 ` [PATCH v6 3/4] iommu/arm-smmu: Add global/context fault implementation hooks Krishna Reddy
2020-06-04 23:44 ` Krishna Reddy
2020-06-04 23:44 ` Krishna Reddy
2020-06-04 23:44 ` Krishna Reddy
2020-06-23 8:36 ` Thierry Reding [this message]
2020-06-23 8:36 ` Thierry Reding
2020-06-23 8:36 ` Thierry Reding
2020-06-23 11:30 ` Robin Murphy
2020-06-23 11:30 ` Robin Murphy
2020-06-23 11:30 ` Robin Murphy
2020-06-23 12:33 ` Thierry Reding
2020-06-23 12:33 ` Thierry Reding
2020-06-23 12:33 ` Thierry Reding
2020-06-04 23:44 ` [PATCH v6 4/4] iommu/arm-smmu-nvidia: fix the warning reported by kbuild test robot Krishna Reddy
2020-06-04 23:44 ` Krishna Reddy
2020-06-04 23:44 ` Krishna Reddy
2020-06-04 23:44 ` Krishna Reddy
2020-06-23 8:33 ` Thierry Reding
2020-06-23 8:33 ` Thierry Reding
2020-06-23 8:33 ` Thierry Reding
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200623083643.GB4098287@ulmo \
--to=thierry.reding@gmail.com \
--cc=bbiswas@nvidia.com \
--cc=bhuntsman@nvidia.com \
--cc=iommu@lists.linux-foundation.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-tegra@vger.kernel.org \
--cc=mperttunen@nvidia.com \
--cc=nicolinc@nvidia.com \
--cc=praithatha@nvidia.com \
--cc=robin.murphy@arm.com \
--cc=snikam@nvidia.com \
--cc=talho@nvidia.com \
--cc=treding@nvidia.com \
--cc=vdumpa@nvidia.com \
--cc=will@kernel.org \
--cc=yhsu@nvidia.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.