iommu/amd: Generalize log overflow handling
authorVasant Hegde <vasant.hegde@amd.com>
Wed, 28 Jun 2023 05:16:23 +0000 (05:16 +0000)
committerJoerg Roedel <jroedel@suse.de>
Fri, 14 Jul 2023 14:19:36 +0000 (16:19 +0200)
Each IOMMU has three log buffers (Event, GA and PPR log). Once a buffer
becomes full, IOMMU generates an interrupt with the corresponding overflow
status bit, and stop processing the log. To handle an overflow, the IOMMU
driver needs to disable the log, clear the overflow status bit, and
re-enable the log. This procedure is same among all types of log
buffer except it uses different overflow status bit and enabling bit.

Hence, to consolidate the log buffer restarting logic, introduce a helper
function amd_iommu_restart_log(), which caller can specify parameters
specific for each type of log buffer.

Also rename MMIO_STATUS_EVT_OVERFLOW_INT_MASK as
MMIO_STATUS_EVT_OVERFLOW_MASK.

Reviewed-by: Jerry Snitselaar <jsnitsel@redhat.com>
Reviewed-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
Reviewed-by: Joao Martins <joao.m.martins@oracle.com>
Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
Link: https://lore.kernel.org/r/20230628051624.5792-2-vasant.hegde@amd.com
Signed-off-by: Joerg Roedel <jroedel@suse.de>
drivers/iommu/amd/amd_iommu_types.h
drivers/iommu/amd/init.c
drivers/iommu/amd/iommu.c

index dc1db6167927910939cdf9d5d749fdbeedf9e5bd..7c436ba2a0a2362da82a30e1cb8caadd0aa2d931 100644 (file)
 #define PASID_MASK             0x0000ffff
 
 /* MMIO status bits */
-#define MMIO_STATUS_EVT_OVERFLOW_INT_MASK      BIT(0)
+#define MMIO_STATUS_EVT_OVERFLOW_MASK          BIT(0)
 #define MMIO_STATUS_EVT_INT_MASK               BIT(1)
 #define MMIO_STATUS_COM_WAIT_INT_MASK          BIT(2)
+#define MMIO_STATUS_EVT_RUN_MASK               BIT(3)
 #define MMIO_STATUS_PPR_INT_MASK               BIT(6)
 #define MMIO_STATUS_GALOG_RUN_MASK             BIT(8)
 #define MMIO_STATUS_GALOG_OVERFLOW_MASK                BIT(9)
index ea0f1ab94178373094f9eff87a4512c7781b3e22..7fab6ecb629584293f9f50d7cc92c567ada121b5 100644 (file)
@@ -752,38 +752,51 @@ static int __init alloc_command_buffer(struct amd_iommu *iommu)
        return iommu->cmd_buf ? 0 : -ENOMEM;
 }
 
+/*
+ * Interrupt handler has processed all pending events and adjusted head
+ * and tail pointer. Reset overflow mask and restart logging again.
+ */
+static void amd_iommu_restart_log(struct amd_iommu *iommu, const char *evt_type,
+                                 u8 cntrl_intr, u8 cntrl_log,
+                                 u32 status_run_mask, u32 status_overflow_mask)
+{
+       u32 status;
+
+       status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET);
+       if (status & status_run_mask)
+               return;
+
+       pr_info_ratelimited("IOMMU %s log restarting\n", evt_type);
+
+       iommu_feature_disable(iommu, cntrl_log);
+       iommu_feature_disable(iommu, cntrl_intr);
+
+       writel(status_overflow_mask, iommu->mmio_base + MMIO_STATUS_OFFSET);
+
+       iommu_feature_enable(iommu, cntrl_intr);
+       iommu_feature_enable(iommu, cntrl_log);
+}
+
 /*
  * This function restarts event logging in case the IOMMU experienced
  * an event log buffer overflow.
  */
 void amd_iommu_restart_event_logging(struct amd_iommu *iommu)
 {
-       iommu_feature_disable(iommu, CONTROL_EVT_LOG_EN);
-       iommu_feature_enable(iommu, CONTROL_EVT_LOG_EN);
+       amd_iommu_restart_log(iommu, "Event", CONTROL_EVT_INT_EN,
+                             CONTROL_EVT_LOG_EN, MMIO_STATUS_EVT_RUN_MASK,
+                             MMIO_STATUS_EVT_OVERFLOW_MASK);
 }
 
 /*
  * This function restarts event logging in case the IOMMU experienced
- * an GA log overflow.
+ * GA log overflow.
  */
 void amd_iommu_restart_ga_log(struct amd_iommu *iommu)
 {
-       u32 status;
-
-       status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET);
-       if (status & MMIO_STATUS_GALOG_RUN_MASK)
-               return;
-
-       pr_info_ratelimited("IOMMU GA Log restarting\n");
-
-       iommu_feature_disable(iommu, CONTROL_GALOG_EN);
-       iommu_feature_disable(iommu, CONTROL_GAINT_EN);
-
-       writel(MMIO_STATUS_GALOG_OVERFLOW_MASK,
-              iommu->mmio_base + MMIO_STATUS_OFFSET);
-
-       iommu_feature_enable(iommu, CONTROL_GAINT_EN);
-       iommu_feature_enable(iommu, CONTROL_GALOG_EN);
+       amd_iommu_restart_log(iommu, "GA", CONTROL_GAINT_EN,
+                             CONTROL_GALOG_EN, MMIO_STATUS_GALOG_RUN_MASK,
+                             MMIO_STATUS_GALOG_OVERFLOW_MASK);
 }
 
 /*
index c3b58a8389b9bff28db96b42289ff1af7db64dc6..86c0ae34373b53dd46e836a59da20246da9c9b92 100644 (file)
@@ -842,7 +842,7 @@ amd_iommu_set_pci_msi_domain(struct device *dev, struct amd_iommu *iommu) { }
 #endif /* !CONFIG_IRQ_REMAP */
 
 #define AMD_IOMMU_INT_MASK     \
-       (MMIO_STATUS_EVT_OVERFLOW_INT_MASK | \
+       (MMIO_STATUS_EVT_OVERFLOW_MASK | \
         MMIO_STATUS_EVT_INT_MASK | \
         MMIO_STATUS_PPR_INT_MASK | \
         MMIO_STATUS_GALOG_OVERFLOW_MASK | \
@@ -881,7 +881,7 @@ irqreturn_t amd_iommu_int_thread(int irq, void *data)
                }
 #endif
 
-               if (status & MMIO_STATUS_EVT_OVERFLOW_INT_MASK) {
+               if (status & MMIO_STATUS_EVT_OVERFLOW_MASK) {
                        pr_info_ratelimited("IOMMU event log overflow\n");
                        amd_iommu_restart_event_logging(iommu);
                }