In the current IOMMU subsystem, IO page fault processing has delays or unresponsive problems. By adding a tunable setup parameter, users can decide whether to use a timeout timer to prevent unresponsive problems.
This implementation refers to Intel's previous patch, URL: https://lore.kernel.org/lkml/1565900005-62508-2-git- send-email-jacob.jun.pan@linux.intel.com/
Signed-off-by: Longfang Liu liulongfang@huawei.com --- .../admin-guide/kernel-parameters.txt | 8 +++++ drivers/iommu/io-pgfault.c | 32 +++++++++++++++++++ 2 files changed, 40 insertions(+)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 6b838869554b..425d446d92c6 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -2176,6 +2176,14 @@ 1 - Bypass the IOMMU for DMA. unset - Use value of CONFIG_IOMMU_DEFAULT_PASSTHROUGH.
+ iommu.iopf_timeout= + Timeout in milliseconds to wait for page response + of a IO page fault request. + Format: <integer> + Default: 600 + 0 - no timeout tracking + 100 to 10000 - allowed range + io7= [HW] IO7 for Marvel-based Alpha systems See comment before marvel_specify_io7 in arch/alpha/kernel/core_marvel.c. diff --git a/drivers/iommu/io-pgfault.c b/drivers/iommu/io-pgfault.c index e5b8b9110c13..cd7ebbfe4a67 100644 --- a/drivers/iommu/io-pgfault.c +++ b/drivers/iommu/io-pgfault.c @@ -45,6 +45,17 @@ struct iopf_fault { struct list_head list; };
+/** + * Timeout to wait for page response of a pending page request. This is + * intended as a basic safety net in case a pending page request is not + * responded for an exceptionally long time. Device may also implement + * its own protection mechanism against this exception. + * default to 600 milliseconds. + */ +#define IOPF_RESPONSE_DEF_TIMEOUT 600 +#define IOPF_RESPONSE_MAX_TIMEOUT 10000 +static unsigned long iopf_timeout_ms = IOPF_RESPONSE_DEF_TIMEOUT; + struct iopf_group { struct iopf_fault last_fault; struct list_head faults; @@ -52,6 +63,27 @@ struct iopf_group { struct device *dev; };
+static int __init iommu_set_iopf_timeout(char *str) +{ + unsigned long timeout; + int ret; + + if (!str) + return -EINVAL; + + ret = kstrtoul(str, 10, &timeout); + if (ret) + return ret; + + if (timeout > IOPF_RESPONSE_MAX_TIMEOUT) + return -EINVAL; + + iopf_timeout_ms = timeout; + + return 0; +} +early_param("iommu.iopf_timeout", iommu_set_iopf_timeout); + static int iopf_complete_group(struct device *dev, struct iopf_fault *iopf, enum iommu_page_response_code status) {