These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / misc / cxl / irq.c
index c8929c5..09a4060 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/slab.h>
 #include <linux/pid.h>
 #include <asm/cputable.h>
-#include <misc/cxl.h>
+#include <misc/cxl-base.h>
 
 #include "cxl.h"
 #include "trace.h"
@@ -30,12 +30,12 @@ static irqreturn_t handle_psl_slice_error(struct cxl_context *ctx, u64 dsisr, u6
        serr = cxl_p1n_read(ctx->afu, CXL_PSL_SERR_An);
        afu_debug = cxl_p1n_read(ctx->afu, CXL_AFU_DEBUG_An);
 
-       dev_crit(&ctx->afu->dev, "PSL ERROR STATUS: 0x%.16llx\n", errstat);
-       dev_crit(&ctx->afu->dev, "PSL_FIR1: 0x%.16llx\n", fir1);
-       dev_crit(&ctx->afu->dev, "PSL_FIR2: 0x%.16llx\n", fir2);
-       dev_crit(&ctx->afu->dev, "PSL_SERR_An: 0x%.16llx\n", serr);
-       dev_crit(&ctx->afu->dev, "PSL_FIR_SLICE_An: 0x%.16llx\n", fir_slice);
-       dev_crit(&ctx->afu->dev, "CXL_PSL_AFU_DEBUG_An: 0x%.16llx\n", afu_debug);
+       dev_crit(&ctx->afu->dev, "PSL ERROR STATUS: 0x%016llx\n", errstat);
+       dev_crit(&ctx->afu->dev, "PSL_FIR1: 0x%016llx\n", fir1);
+       dev_crit(&ctx->afu->dev, "PSL_FIR2: 0x%016llx\n", fir2);
+       dev_crit(&ctx->afu->dev, "PSL_SERR_An: 0x%016llx\n", serr);
+       dev_crit(&ctx->afu->dev, "PSL_FIR_SLICE_An: 0x%016llx\n", fir_slice);
+       dev_crit(&ctx->afu->dev, "CXL_PSL_AFU_DEBUG_An: 0x%016llx\n", afu_debug);
 
        dev_crit(&ctx->afu->dev, "STOPPING CXL TRACE\n");
        cxl_stop_trace(ctx->afu->adapter);
@@ -54,10 +54,10 @@ irqreturn_t cxl_slice_irq_err(int irq, void *data)
        fir_slice = cxl_p1n_read(afu, CXL_PSL_FIR_SLICE_An);
        errstat = cxl_p2n_read(afu, CXL_PSL_ErrStat_An);
        afu_debug = cxl_p1n_read(afu, CXL_AFU_DEBUG_An);
-       dev_crit(&afu->dev, "PSL_SERR_An: 0x%.16llx\n", serr);
-       dev_crit(&afu->dev, "PSL_FIR_SLICE_An: 0x%.16llx\n", fir_slice);
-       dev_crit(&afu->dev, "CXL_PSL_ErrStat_An: 0x%.16llx\n", errstat);
-       dev_crit(&afu->dev, "CXL_PSL_AFU_DEBUG_An: 0x%.16llx\n", afu_debug);
+       dev_crit(&afu->dev, "PSL_SERR_An: 0x%016llx\n", serr);
+       dev_crit(&afu->dev, "PSL_FIR_SLICE_An: 0x%016llx\n", fir_slice);
+       dev_crit(&afu->dev, "CXL_PSL_ErrStat_An: 0x%016llx\n", errstat);
+       dev_crit(&afu->dev, "CXL_PSL_AFU_DEBUG_An: 0x%016llx\n", afu_debug);
 
        cxl_p1n_write(afu, CXL_PSL_SERR_An, serr);
 
@@ -72,7 +72,7 @@ static irqreturn_t cxl_irq_err(int irq, void *data)
        WARN(1, "CXL ERROR interrupt %i\n", irq);
 
        err_ivte = cxl_p1_read(adapter, CXL_PSL_ErrIVTE);
-       dev_crit(&adapter->dev, "PSL_ErrIVTE: 0x%.16llx\n", err_ivte);
+       dev_crit(&adapter->dev, "PSL_ErrIVTE: 0x%016llx\n", err_ivte);
 
        dev_crit(&adapter->dev, "STOPPING CXL TRACE\n");
        cxl_stop_trace(adapter);
@@ -80,7 +80,7 @@ static irqreturn_t cxl_irq_err(int irq, void *data)
        fir1 = cxl_p1_read(adapter, CXL_PSL_FIR1);
        fir2 = cxl_p1_read(adapter, CXL_PSL_FIR2);
 
-       dev_crit(&adapter->dev, "PSL_FIR1: 0x%.16llx\nPSL_FIR2: 0x%.16llx\n", fir1, fir2);
+       dev_crit(&adapter->dev, "PSL_FIR1: 0x%016llx\nPSL_FIR2: 0x%016llx\n", fir1, fir2);
 
        return IRQ_HANDLED;
 }
@@ -147,7 +147,7 @@ static irqreturn_t cxl_irq(int irq, void *data, struct cxl_irq_info *irq_info)
        if (dsisr & CXL_PSL_DSISR_An_PE)
                return handle_psl_slice_error(ctx, dsisr, irq_info->errstat);
        if (dsisr & CXL_PSL_DSISR_An_AE) {
-               pr_devel("CXL interrupt: AFU Error %.llx\n", irq_info->afu_err);
+               pr_devel("CXL interrupt: AFU Error 0x%016llx\n", irq_info->afu_err);
 
                if (ctx->pending_afu_err) {
                        /*
@@ -158,7 +158,7 @@ static irqreturn_t cxl_irq(int irq, void *data, struct cxl_irq_info *irq_info)
                         * probably best that we log them somewhere:
                         */
                        dev_err_ratelimited(&ctx->afu->dev, "CXL AFU Error "
-                                           "undelivered to pe %i: %.llx\n",
+                                           "undelivered to pe %i: 0x%016llx\n",
                                            ctx->pe, irq_info->afu_err);
                } else {
                        spin_lock(&ctx->lock);
@@ -211,8 +211,8 @@ static irqreturn_t cxl_irq_multiplexed(int irq, void *data)
        }
        rcu_read_unlock();
 
-       WARN(1, "Unable to demultiplex CXL PSL IRQ for PE %i DSISR %.16llx DAR"
-               " %.16llx\n(Possible AFU HW issue - was a term/remove acked"
+       WARN(1, "Unable to demultiplex CXL PSL IRQ for PE %i DSISR %016llx DAR"
+               " %016llx\n(Possible AFU HW issue - was a term/remove acked"
                " with outstanding transactions?)\n", ph, irq_info.dsisr,
                irq_info.dar);
        return fail_psl_irq(afu, &irq_info);
@@ -341,6 +341,9 @@ int cxl_register_psl_err_irq(struct cxl *adapter)
 
 void cxl_release_psl_err_irq(struct cxl *adapter)
 {
+       if (adapter->err_virq != irq_find_mapping(NULL, adapter->err_hwirq))
+               return;
+
        cxl_p1_write(adapter, CXL_PSL_ErrIVTE, 0x0000000000000000);
        cxl_unmap_irq(adapter->err_virq, adapter);
        cxl_release_one_irq(adapter, adapter->err_hwirq);
@@ -374,6 +377,9 @@ int cxl_register_serr_irq(struct cxl_afu *afu)
 
 void cxl_release_serr_irq(struct cxl_afu *afu)
 {
+       if (afu->serr_virq != irq_find_mapping(NULL, afu->serr_hwirq))
+               return;
+
        cxl_p1n_write(afu, CXL_PSL_SERR_An, 0x0000000000000000);
        cxl_unmap_irq(afu->serr_virq, afu);
        cxl_release_one_irq(afu->adapter, afu->serr_hwirq);
@@ -400,6 +406,9 @@ int cxl_register_psl_irq(struct cxl_afu *afu)
 
 void cxl_release_psl_irq(struct cxl_afu *afu)
 {
+       if (afu->psl_virq != irq_find_mapping(NULL, afu->psl_hwirq))
+               return;
+
        cxl_unmap_irq(afu->psl_virq, afu);
        cxl_release_one_irq(afu->adapter, afu->psl_hwirq);
        kfree(afu->psl_irq_name);
@@ -416,12 +425,14 @@ void afu_irq_name_free(struct cxl_context *ctx)
        }
 }
 
-int afu_register_irqs(struct cxl_context *ctx, u32 count)
+int afu_allocate_irqs(struct cxl_context *ctx, u32 count)
 {
-       irq_hw_number_t hwirq;
        int rc, r, i, j = 1;
        struct cxl_irq_name *irq_name;
 
+       /* Initialize the list head to hold irq names */
+       INIT_LIST_HEAD(&ctx->irq_names);
+
        if ((rc = cxl_alloc_irq_ranges(&ctx->irqs, ctx->afu->adapter, count)))
                return rc;
 
@@ -433,13 +444,12 @@ int afu_register_irqs(struct cxl_context *ctx, u32 count)
        ctx->irq_bitmap = kcalloc(BITS_TO_LONGS(count),
                                  sizeof(*ctx->irq_bitmap), GFP_KERNEL);
        if (!ctx->irq_bitmap)
-               return -ENOMEM;
+               goto out;
 
        /*
         * Allocate names first.  If any fail, bail out before allocating
         * actual hardware IRQs.
         */
-       INIT_LIST_HEAD(&ctx->irq_names);
        for (r = 1; r < CXL_IRQ_RANGES; r++) {
                for (i = 0; i < ctx->irqs.range[r]; i++) {
                        irq_name = kmalloc(sizeof(struct cxl_irq_name),
@@ -458,6 +468,19 @@ int afu_register_irqs(struct cxl_context *ctx, u32 count)
                        j++;
                }
        }
+       return 0;
+
+out:
+       cxl_release_irq_ranges(&ctx->irqs, ctx->afu->adapter);
+       afu_irq_name_free(ctx);
+       return -ENOMEM;
+}
+
+static void afu_register_hwirqs(struct cxl_context *ctx)
+{
+       irq_hw_number_t hwirq;
+       struct cxl_irq_name *irq_name;
+       int r,i;
 
        /* We've allocated all memory now, so let's do the irq allocations */
        irq_name = list_first_entry(&ctx->irq_names, struct cxl_irq_name, list);
@@ -469,15 +492,21 @@ int afu_register_irqs(struct cxl_context *ctx, u32 count)
                        irq_name = list_next_entry(irq_name, list);
                }
        }
+}
 
-       return 0;
+int afu_register_irqs(struct cxl_context *ctx, u32 count)
+{
+       int rc;
 
-out:
-       afu_irq_name_free(ctx);
-       return -ENOMEM;
-}
+       rc = afu_allocate_irqs(ctx, count);
+       if (rc)
+               return rc;
+
+       afu_register_hwirqs(ctx);
+       return 0;
+ }
 
-void afu_release_irqs(struct cxl_context *ctx)
+void afu_release_irqs(struct cxl_context *ctx, void *cookie)
 {
        irq_hw_number_t hwirq;
        unsigned int virq;
@@ -488,10 +517,12 @@ void afu_release_irqs(struct cxl_context *ctx)
                for (i = 0; i < ctx->irqs.range[r]; hwirq++, i++) {
                        virq = irq_find_mapping(NULL, hwirq);
                        if (virq)
-                               cxl_unmap_irq(virq, ctx);
+                               cxl_unmap_irq(virq, cookie);
                }
        }
 
        afu_irq_name_free(ctx);
        cxl_release_irq_ranges(&ctx->irqs, ctx->afu->adapter);
+
+       ctx->irq_count = 0;
 }