From 72f5f2a78eebc52d567d4daa39a8bba431942846 Mon Sep 17 00:00:00 2001 From: Knut Omang Date: Mon, 18 Jul 2016 13:30:01 +0200 Subject: [PATCH] sif: eq: Avoid enabling interrupts on TSU EQs until the initialization is complete MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: HÃ¥kon Bugge --- drivers/infiniband/hw/sif/sif_dev.h | 1 + drivers/infiniband/hw/sif/sif_eq.c | 70 ++++++++++++++++++++++------ drivers/infiniband/hw/sif/sif_eq.h | 3 ++ drivers/infiniband/hw/sif/sif_main.c | 7 ++- 4 files changed, 65 insertions(+), 16 deletions(-) diff --git a/drivers/infiniband/hw/sif/sif_dev.h b/drivers/infiniband/hw/sif/sif_dev.h index 9908e3c8314c..fb26904d4098 100644 --- a/drivers/infiniband/hw/sif/sif_dev.h +++ b/drivers/infiniband/hw/sif/sif_dev.h @@ -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 */ diff --git a/drivers/infiniband/hw/sif/sif_eq.c b/drivers/infiniband/hw/sif/sif_eq.c index b8fe6723776c..9112e43a8986 100644 --- a/drivers/infiniband/hw/sif/sif_eq.c +++ b/drivers/infiniband/hw/sif/sif_eq.c @@ -26,6 +26,8 @@ #include 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); diff --git a/drivers/infiniband/hw/sif/sif_eq.h b/drivers/infiniband/hw/sif/sif_eq.h index 0b7c114a6357..a939253f334e 100644 --- a/drivers/infiniband/hw/sif/sif_eq.h +++ b/drivers/infiniband/hw/sif/sif_eq.h @@ -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); diff --git a/drivers/infiniband/hw/sif/sif_main.c b/drivers/infiniband/hw/sif/sif_main.c index 3bcd05c278b4..2c3c7a5d7739 100644 --- a/drivers/infiniband/hw/sif/sif_main.c +++ b/drivers/infiniband/hw/sif/sif_main.c @@ -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, -- 2.50.1