|
@@ -24,6 +24,7 @@
|
|
|
#include <linux/acpi_iort.h>
|
|
|
#include <linux/bitfield.h>
|
|
|
#include <linux/bitops.h>
|
|
|
+#include <linux/crash_dump.h>
|
|
|
#include <linux/delay.h>
|
|
|
#include <linux/dma-iommu.h>
|
|
|
#include <linux/err.h>
|
|
@@ -2212,8 +2213,12 @@ static int arm_smmu_update_gbpa(struct arm_smmu_device *smmu, u32 set, u32 clr)
|
|
|
reg &= ~clr;
|
|
|
reg |= set;
|
|
|
writel_relaxed(reg | GBPA_UPDATE, gbpa);
|
|
|
- return readl_relaxed_poll_timeout(gbpa, reg, !(reg & GBPA_UPDATE),
|
|
|
- 1, ARM_SMMU_POLL_TIMEOUT_US);
|
|
|
+ ret = readl_relaxed_poll_timeout(gbpa, reg, !(reg & GBPA_UPDATE),
|
|
|
+ 1, ARM_SMMU_POLL_TIMEOUT_US);
|
|
|
+
|
|
|
+ if (ret)
|
|
|
+ dev_err(smmu->dev, "GBPA not responding to update\n");
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
static void arm_smmu_free_msis(void *data)
|
|
@@ -2393,8 +2398,15 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool bypass)
|
|
|
|
|
|
/* Clear CR0 and sync (disables SMMU and queue processing) */
|
|
|
reg = readl_relaxed(smmu->base + ARM_SMMU_CR0);
|
|
|
- if (reg & CR0_SMMUEN)
|
|
|
+ if (reg & CR0_SMMUEN) {
|
|
|
+ if (is_kdump_kernel()) {
|
|
|
+ arm_smmu_update_gbpa(smmu, GBPA_ABORT, 0);
|
|
|
+ arm_smmu_device_disable(smmu);
|
|
|
+ return -EBUSY;
|
|
|
+ }
|
|
|
+
|
|
|
dev_warn(smmu->dev, "SMMU currently enabled! Resetting...\n");
|
|
|
+ }
|
|
|
|
|
|
ret = arm_smmu_device_disable(smmu);
|
|
|
if (ret)
|
|
@@ -2492,10 +2504,8 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool bypass)
|
|
|
enables |= CR0_SMMUEN;
|
|
|
} else {
|
|
|
ret = arm_smmu_update_gbpa(smmu, 0, GBPA_ABORT);
|
|
|
- if (ret) {
|
|
|
- dev_err(smmu->dev, "GBPA not responding to update\n");
|
|
|
+ if (ret)
|
|
|
return ret;
|
|
|
- }
|
|
|
}
|
|
|
ret = arm_smmu_write_reg_sync(smmu, enables, ARM_SMMU_CR0,
|
|
|
ARM_SMMU_CR0ACK);
|