Skip to content

Commit 2e8db98

Browse files
authored
iommu/arm-smmu: Use pm_runtime in fault handlers (#425)
iommu/arm-smmu: Use pm_runtime in fault handlers
2 parents 085c63c + 9aa667a commit 2e8db98

1 file changed

Lines changed: 39 additions & 21 deletions

File tree

drivers/iommu/arm/arm-smmu/arm-smmu.c

Lines changed: 39 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -462,10 +462,20 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev)
462462
int idx = smmu_domain->cfg.cbndx;
463463
int ret;
464464

465+
if (!pm_runtime_get_if_active(smmu->dev))
466+
return IRQ_NONE;
467+
468+
if (smmu->impl && smmu->impl->context_fault) {
469+
ret = smmu->impl->context_fault(irq, dev);
470+
goto out_power_off;
471+
}
472+
465473
arm_smmu_read_context_fault_info(smmu, idx, &cfi);
466474

467-
if (!(cfi.fsr & ARM_SMMU_CB_FSR_FAULT))
468-
return IRQ_NONE;
475+
if (!(cfi.fsr & ARM_SMMU_CB_FSR_FAULT)) {
476+
ret = IRQ_NONE;
477+
goto out_power_off;
478+
}
469479

470480
ret = report_iommu_fault(&smmu_domain->domain, NULL, cfi.iova,
471481
cfi.fsynr & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
@@ -480,7 +490,12 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev)
480490
ret == -EAGAIN ? 0 : ARM_SMMU_RESUME_TERMINATE);
481491
}
482492

483-
return IRQ_HANDLED;
493+
ret = IRQ_HANDLED;
494+
495+
out_power_off:
496+
pm_runtime_put_autosuspend(smmu->dev);
497+
498+
return ret;
484499
}
485500

486501
static irqreturn_t arm_smmu_global_fault(int irq, void *dev)
@@ -489,14 +504,25 @@ static irqreturn_t arm_smmu_global_fault(int irq, void *dev)
489504
struct arm_smmu_device *smmu = dev;
490505
static DEFINE_RATELIMIT_STATE(rs, DEFAULT_RATELIMIT_INTERVAL,
491506
DEFAULT_RATELIMIT_BURST);
507+
int ret;
508+
509+
if (!pm_runtime_get_if_active(smmu->dev))
510+
return IRQ_NONE;
511+
512+
if (smmu->impl && smmu->impl->global_fault) {
513+
ret = smmu->impl->global_fault(irq, dev);
514+
goto out_power_off;
515+
}
492516

493517
gfsr = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_sGFSR);
494518
gfsynr0 = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_sGFSYNR0);
495519
gfsynr1 = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_sGFSYNR1);
496520
gfsynr2 = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_sGFSYNR2);
497521

498-
if (!gfsr)
499-
return IRQ_NONE;
522+
if (!gfsr) {
523+
ret = IRQ_NONE;
524+
goto out_power_off;
525+
}
500526

501527
if (__ratelimit(&rs)) {
502528
if (IS_ENABLED(CONFIG_ARM_SMMU_DISABLE_BYPASS_BY_DEFAULT) &&
@@ -513,7 +539,11 @@ static irqreturn_t arm_smmu_global_fault(int irq, void *dev)
513539
}
514540

515541
arm_smmu_gr0_write(smmu, ARM_SMMU_GR0_sGFSR, gfsr);
516-
return IRQ_HANDLED;
542+
ret = IRQ_HANDLED;
543+
544+
out_power_off:
545+
pm_runtime_put_autosuspend(smmu->dev);
546+
return ret;
517547
}
518548

519549
static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain,
@@ -683,7 +713,6 @@ static int arm_smmu_init_domain_context(struct arm_smmu_domain *smmu_domain,
683713
enum io_pgtable_fmt fmt;
684714
struct iommu_domain *domain = &smmu_domain->domain;
685715
struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
686-
irqreturn_t (*context_fault)(int irq, void *dev);
687716

688717
mutex_lock(&smmu_domain->init_mutex);
689718
if (smmu_domain->smmu)
@@ -850,19 +879,14 @@ static int arm_smmu_init_domain_context(struct arm_smmu_domain *smmu_domain,
850879
*/
851880
irq = smmu->irqs[cfg->irptndx];
852881

853-
if (smmu->impl && smmu->impl->context_fault)
854-
context_fault = smmu->impl->context_fault;
855-
else
856-
context_fault = arm_smmu_context_fault;
857-
858882
if (smmu->impl && smmu->impl->context_fault_needs_threaded_irq)
859883
ret = devm_request_threaded_irq(smmu->dev, irq, NULL,
860-
context_fault,
884+
arm_smmu_context_fault,
861885
IRQF_ONESHOT | IRQF_SHARED,
862886
"arm-smmu-context-fault",
863887
smmu_domain);
864888
else
865-
ret = devm_request_irq(smmu->dev, irq, context_fault, IRQF_SHARED,
889+
ret = devm_request_irq(smmu->dev, irq, arm_smmu_context_fault, IRQF_SHARED,
866890
"arm-smmu-context-fault", smmu_domain);
867891

868892
if (ret < 0) {
@@ -2122,7 +2146,6 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
21222146
struct device *dev = &pdev->dev;
21232147
int num_irqs, i, err;
21242148
u32 global_irqs, pmu_irqs;
2125-
irqreturn_t (*global_fault)(int irq, void *dev);
21262149

21272150
smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL);
21282151
if (!smmu) {
@@ -2202,18 +2225,13 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
22022225
smmu->num_context_irqs = smmu->num_context_banks;
22032226
}
22042227

2205-
if (smmu->impl && smmu->impl->global_fault)
2206-
global_fault = smmu->impl->global_fault;
2207-
else
2208-
global_fault = arm_smmu_global_fault;
2209-
22102228
for (i = 0; i < global_irqs; i++) {
22112229
int irq = platform_get_irq(pdev, i);
22122230

22132231
if (irq < 0)
22142232
return irq;
22152233

2216-
err = devm_request_irq(dev, irq, global_fault, IRQF_SHARED,
2234+
err = devm_request_irq(dev, irq, arm_smmu_global_fault, IRQF_SHARED,
22172235
"arm-smmu global fault", smmu);
22182236
if (err)
22192237
return dev_err_probe(dev, err,

0 commit comments

Comments
 (0)