Merge tag 'iommu-updates-v6.6' of git://git.kernel.org/pub/scm/linux/kernel/git/joro...
[platform/kernel/linux-rpi.git] / drivers / iommu / amd / iommu.c
index 7d7d379..95bd7c2 100644 (file)
@@ -841,50 +841,27 @@ static inline void
 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_INT_MASK | \
-        MMIO_STATUS_PPR_INT_MASK | \
-        MMIO_STATUS_GALOG_OVERFLOW_MASK | \
-        MMIO_STATUS_GALOG_INT_MASK)
-
-irqreturn_t amd_iommu_int_thread(int irq, void *data)
+static void amd_iommu_handle_irq(void *data, const char *evt_type,
+                                u32 int_mask, u32 overflow_mask,
+                                void (*int_handler)(struct amd_iommu *),
+                                void (*overflow_handler)(struct amd_iommu *))
 {
        struct amd_iommu *iommu = (struct amd_iommu *) data;
        u32 status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET);
+       u32 mask = int_mask | overflow_mask;
 
-       while (status & AMD_IOMMU_INT_MASK) {
+       while (status & mask) {
                /* Enable interrupt sources again */
-               writel(AMD_IOMMU_INT_MASK,
-                       iommu->mmio_base + MMIO_STATUS_OFFSET);
+               writel(mask, iommu->mmio_base + MMIO_STATUS_OFFSET);
 
-               if (status & MMIO_STATUS_EVT_INT_MASK) {
-                       pr_devel("Processing IOMMU Event Log\n");
-                       iommu_poll_events(iommu);
+               if (int_handler) {
+                       pr_devel("Processing IOMMU (ivhd%d) %s Log\n",
+                                iommu->index, evt_type);
+                       int_handler(iommu);
                }
 
-               if (status & MMIO_STATUS_PPR_INT_MASK) {
-                       pr_devel("Processing IOMMU PPR Log\n");
-                       iommu_poll_ppr_log(iommu);
-               }
-
-#ifdef CONFIG_IRQ_REMAP
-               if (status & (MMIO_STATUS_GALOG_INT_MASK |
-                             MMIO_STATUS_GALOG_OVERFLOW_MASK)) {
-                       pr_devel("Processing IOMMU GA Log\n");
-                       iommu_poll_ga_log(iommu);
-               }
-
-               if (status & MMIO_STATUS_GALOG_OVERFLOW_MASK) {
-                       pr_info_ratelimited("IOMMU GA Log overflow\n");
-                       amd_iommu_restart_ga_log(iommu);
-               }
-#endif
-
-               if (status & MMIO_STATUS_EVT_OVERFLOW_INT_MASK) {
-                       pr_info_ratelimited("IOMMU event log overflow\n");
-                       amd_iommu_restart_event_logging(iommu);
-               }
+               if ((status & overflow_mask) && overflow_handler)
+                       overflow_handler(iommu);
 
                /*
                 * Hardware bug: ERBT1312
@@ -901,6 +878,43 @@ irqreturn_t amd_iommu_int_thread(int irq, void *data)
                 */
                status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET);
        }
+}
+
+irqreturn_t amd_iommu_int_thread_evtlog(int irq, void *data)
+{
+       amd_iommu_handle_irq(data, "Evt", MMIO_STATUS_EVT_INT_MASK,
+                            MMIO_STATUS_EVT_OVERFLOW_MASK,
+                            iommu_poll_events, amd_iommu_restart_event_logging);
+
+       return IRQ_HANDLED;
+}
+
+irqreturn_t amd_iommu_int_thread_pprlog(int irq, void *data)
+{
+       amd_iommu_handle_irq(data, "PPR", MMIO_STATUS_PPR_INT_MASK,
+                            MMIO_STATUS_PPR_OVERFLOW_MASK,
+                            iommu_poll_ppr_log, amd_iommu_restart_ppr_log);
+
+       return IRQ_HANDLED;
+}
+
+irqreturn_t amd_iommu_int_thread_galog(int irq, void *data)
+{
+#ifdef CONFIG_IRQ_REMAP
+       amd_iommu_handle_irq(data, "GA", MMIO_STATUS_GALOG_INT_MASK,
+                            MMIO_STATUS_GALOG_OVERFLOW_MASK,
+                            iommu_poll_ga_log, amd_iommu_restart_ga_log);
+#endif
+
+       return IRQ_HANDLED;
+}
+
+irqreturn_t amd_iommu_int_thread(int irq, void *data)
+{
+       amd_iommu_int_thread_evtlog(irq, data);
+       amd_iommu_int_thread_pprlog(irq, data);
+       amd_iommu_int_thread_galog(irq, data);
+
        return IRQ_HANDLED;
 }