]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
sif: eq: Avoid enabling interrupts on TSU EQs until the initialization is complete
authorKnut Omang <knut.omang@oracle.com>
Mon, 18 Jul 2016 11:30:01 +0000 (13:30 +0200)
committerSantosh Shilimkar <santosh.shilimkar@oracle.com>
Wed, 27 Jul 2016 17:24:21 +0000 (10:24 -0700)
During driver load we might have some rare conditions where external events
are occuring before the driver is ready to accept them. The hardware workarounds
to handle issues with QP flushing are particularly sensitive to this.

Delay enabling of the IRQs that can generate interrupts for all
event queues except the EPS event queue(s) until everything is set up and ready.

Note that this commit will also implicitly cause interrupts for EQs 1-3 for each EPSA
not to be enabled. This is no big deal as they are currently not used anyway.

Orabug: 24296729

Signed-off-by: Knut Omang <knut.omang@oracle.com>
Reviewed-by: HÃ¥kon Bugge <haakon.bugge@oracle.com>
drivers/infiniband/hw/sif/sif_dev.h
drivers/infiniband/hw/sif/sif_eq.c
drivers/infiniband/hw/sif/sif_eq.h
drivers/infiniband/hw/sif/sif_main.c

index 9908e3c8314cc10c8ba199929dab5d1516d81f23..fb26904d4098ae004ffdb7e59172e876131e5b30 100644 (file)
@@ -219,6 +219,7 @@ struct sif_eq {
        u32 mask;            /* entries - 1 for modulo using & */
        struct sif_mem *mem;   /* Ref. to ba.mem to implement macro patterns */
        int intr_vec;          /* Index into s->entries[..] for the interrupt vector used */
+       bool requested;        /* Whether the irq has been requested or not on this eq */
        u32 sw_index_interval; /* No. of events we can receive before the sw index must be updated */
        u32 sw_index_next_update; /* Next scheduled update point */
        atomic_t intr_cnt;   /* Number of interrupts for the interrupt vector for this eq */
index b8fe6723776c88266a1f515381fef133f2d9ab33..9112e43a898601cec028b2f0d89902194632f70b 100644 (file)
@@ -26,6 +26,8 @@
 #include <linux/seq_file.h>
 
 static int sif_map_irq(struct sif_eq *eq);
+static int sif_request_irq(struct sif_eq *eq);
+
 static int sif_irq_coalesce(struct sif_eq *eq);
 
 static void sif_unmap_irq(struct sif_eq *eq);
@@ -83,6 +85,17 @@ int sif_eq_init(struct sif_dev *sdev, struct sif_eps *es, struct psif_epsc_csr_r
        }
 
        eqb->cnt = cnt;
+
+       if (cnt) {
+               /* Request irq for the EPS interrupt queue only - all the rest
+                * of the interrupts can be enabled explicitly using sif_eq_request_irq_all
+                * when we are ready to process events of all kinds.
+                * See Orabug: 24296729
+                */
+               ret = sif_request_irq(&eq[0]);
+               if (ret)
+                       goto eqi_failed;
+       }
        return 0;
 
 eqi_failed:
@@ -92,6 +105,22 @@ eqi_failed:
        return ret;
 }
 
+/* Request irq for all eqs still not requested for */
+int sif_eq_request_irq_all(struct sif_eps *es)
+{
+       int ret;
+       int i;
+
+       for (i = 0; i < es->eqs.cnt; i++) {
+               struct sif_eq *eq = &es->eqs.eq[i];
+               if (!eq->requested) {
+                       ret = sif_request_irq(eq);
+                       if (ret)
+                               return ret;
+               }
+       }
+       return 0;
+}
 
 static void sif_eq_deinit_tables(struct sif_dev *sdev, struct sif_eps *es)
 {
@@ -256,7 +285,7 @@ static int sif_eq_table_init(struct sif_dev *sdev, struct sif_eps *es, u16 eq_id
                goto err_map_ctx;
        }
 
-       /* Allocate an irq index */
+       /* Allocate an irq index (but do not yet enable interrupts on it) */
        ret = sif_map_irq(eq);
        if (ret)
                goto err_map_irq;
@@ -382,14 +411,11 @@ opcode_not_available:
        return -1;
 }
 
-/* Interrupt handling for a single event queue */
+/* Set up interrupt handling for a single event queue (but do not enable interrupts) */
 static int sif_map_irq(struct sif_eq *eq)
 {
-       int irq;
-       int ret;
        int vector_num;
        struct sif_dev *s = eq->ba.sdev;
-       int flags = (s->intr_cnt !=  s->intr_req) ? IRQF_SHARED : 0;
        const char *en;
 
        spin_lock(&s->msix_lock);
@@ -405,7 +431,6 @@ static int sif_map_irq(struct sif_eq *eq)
                return -ENOMEM;
        }
 
-       irq = s->msix_entries[vector_num].vector;
        en = eps_name(s, eq->eps->eps_num);
 
        if (eq->index)
@@ -413,29 +438,44 @@ static int sif_map_irq(struct sif_eq *eq)
        else
                snprintf(eq->name, SIF_EQ_NAME_LEN, "sif%d-EPS%s", 0, en);
 
+       sif_log(s, SIF_INFO_V, "Allocated irq %d for EPS%s, eq %d, name %s",
+               s->msix_entries[vector_num].vector, en, eq->index, eq->name);
+       eq->intr_vec = vector_num;
+       return 0;
+}
+
+
+static int sif_request_irq(struct sif_eq *eq)
+{
+       int irq;
+       int vector_num = eq->intr_vec;
+       struct sif_dev *s = eq->ba.sdev;
+       int ret = 0;
+       int flags = (s->intr_cnt !=  s->intr_req) ? IRQF_SHARED : 0;
+
+       irq = s->msix_entries[vector_num].vector;
        ret = request_irq(irq, &sif_intr, flags, eq->name, eq);
        if (ret)
                return ret;
-       sif_log(s, SIF_INFO_V, "Allocated irq %d for EPS%s, eq %d, name %s", irq, en,
-               eq->index, eq->name);
-       eq->intr_vec = vector_num;
 
+       eq->requested = true;
        ret = irq_set_affinity_hint(irq, eq->affinity_mask);
-       if (ret) {
+       if (ret)
                sif_log(s, SIF_INFO_V, "set affinity hint for irq %d, failed", irq);
-               return ret;
-       }
-       return 0;
+       return ret;
 }
 
+
 static void sif_unmap_irq(struct sif_eq *eq)
 {
        struct sif_dev *s = eq->ba.sdev;
        int irq = s->msix_entries[eq->intr_vec].vector;
 
        free_cpumask_var(eq->affinity_mask);
-       irq_set_affinity_hint(irq, NULL);
-       free_irq(irq, eq);
+       if (eq->requested) {
+               irq_set_affinity_hint(irq, NULL);
+               free_irq(irq, eq);
+       }
        spin_lock(&s->msix_lock);
        clear_bit(eq->intr_vec, s->intr_used);
        spin_unlock(&s->msix_lock);
index 0b7c114a635774a5fa74651ef7bd4384c7936073..a939253f334e6f92d68cf8f5552721069a06e381 100644 (file)
@@ -44,6 +44,9 @@ void sif_eq_deinit(struct sif_dev *sdev, struct sif_eps *es);
 int sif_enable_msix(struct sif_dev *s);
 int sif_disable_msix(struct sif_dev *sdev);
 
+/* Request irq for all eqs still not requested for */
+int sif_eq_request_irq_all(struct sif_eps *es);
+
 /* Printer for debugfs eq file */
 void sif_dfs_print_eq(struct seq_file *s, struct sif_dev *sdev, loff_t pos);
 
index 3bcd05c278b4a7812e4aaf0fdfa604a997eea873..2c3c7a5d77395d9111bab4c3944771bd97d355f6 100644 (file)
@@ -365,6 +365,12 @@ static int sif_probe(struct pci_dev *pdev,
                        goto pfail_r3_init;
        }
 
+       es = &sdev->es[sdev->mbox_epsc];
+
+       err = sif_eq_request_irq_all(es);
+       if (err)
+               goto pfail_ibreg;
+
        /* Successful device init */
 
        err = sif_register_ib_device(sdev);
@@ -375,7 +381,6 @@ static int sif_probe(struct pci_dev *pdev,
        sif_dfs_link_to_ibdev(sdev);
 
 
-       es = &sdev->es[sdev->mbox_epsc];
        sif_log(sdev, SIF_INFO, "Enabled %s (hardware v%d.%d - firmware v%d.%d (api v%d.%d))",
                sdev->ib_dev.name,
                es->ver.psif_major, es->ver.psif_minor,