iommu/arm-smmu: Implement DOMAIN_ATTR_NON_FATAL_FAULTS

Unhandled context faults should be fatal unless explicitly requested
otherwise by the client.  Implement the DOMAIN_ATTR_NON_FATAL_FAULTS
attribute for this purpose.

Change-Id: I414fcc6000a6c47b3cbf77b1098c8b7895cbb20d
Signed-off-by: Mitchel Humpherys <mitchelh@codeaurora.org>
Signed-off-by: Patrick Daly <pdaly@codeaurora.org>
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 7ff54f0..28a1737 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -821,6 +821,8 @@
 	bool fatal_asf = smmu->options & ARM_SMMU_OPT_FATAL_ASF;
 	phys_addr_t phys_soft;
 	u32 frsynra;
+	bool non_fatal_fault = !!(smmu_domain->attributes &
+					DOMAIN_ATTR_NON_FATAL_FAULTS);
 
 	static DEFINE_RATELIMIT_STATE(_rs,
 				      DEFAULT_RATELIMIT_INTERVAL,
@@ -896,6 +898,11 @@
 		}
 		ret = IRQ_NONE;
 		resume = RESUME_TERMINATE;
+		if (!non_fatal_fault) {
+			dev_err(smmu->dev,
+				"Unhandled arm-smmu context fault!\n");
+			BUG();
+		}
 	}
 
 	/*
@@ -1870,6 +1877,11 @@
 					& (1 << DOMAIN_ATTR_DYNAMIC));
 		ret = 0;
 		break;
+	case DOMAIN_ATTR_NON_FATAL_FAULTS:
+		*((int *)data) = !!(smmu_domain->attributes
+				    & (1 << DOMAIN_ATTR_NON_FATAL_FAULTS));
+		ret = 0;
+		break;
 	default:
 		return -ENODEV;
 	}
@@ -1940,6 +1952,18 @@
 		smmu_domain->cfg.cbndx = *((unsigned int *)data);
 		ret = 0;
 		break;
+	case DOMAIN_ATTR_NON_FATAL_FAULTS: {
+		u32 non_fatal_faults = *((int *)data);
+
+		if (non_fatal_faults)
+			smmu_domain->attributes |=
+					1 << DOMAIN_ATTR_NON_FATAL_FAULTS;
+		else
+			smmu_domain->attributes &=
+					~(1 << DOMAIN_ATTR_NON_FATAL_FAULTS);
+		ret = 0;
+		break;
+	}
 	default:
 		ret = -ENODEV;
 	}