aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorStefan Roscher <ossrosch@linux.vnet.ibm.com>2008-07-15 02:48:47 -0400
committerRoland Dreier <rolandd@cisco.com>2008-07-15 02:48:47 -0400
commit6f7bc01a7382641c61ec036d68ff3a9140b48a1c (patch)
treedebf518649e7af08c42465f6683bc66322ba1554 /drivers
parent3e255eac561672cbc92844b9f16cae9304c2a783 (diff)
IB/ehca: In case of lost interrupts, trigger EOI to reenable interrupts
During corner case testing, we noticed that some versions of ehca do not properly transition to interrupt done in special load situations. This can be resolved by periodically triggering EOI through H_EOI, if EQEs are pending. Signed-off-by: Stefan Roscher <stefan.roscher@de.ibm.com> Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/infiniband/hw/ehca/ehca_irq.c9
-rw-r--r--drivers/infiniband/hw/ehca/hcp_if.c10
-rw-r--r--drivers/infiniband/hw/ehca/hcp_if.h1
3 files changed, 18 insertions, 2 deletions
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c
index ce1ab0571be3..0792d930c481 100644
--- a/drivers/infiniband/hw/ehca/ehca_irq.c
+++ b/drivers/infiniband/hw/ehca/ehca_irq.c
@@ -531,7 +531,7 @@ void ehca_process_eq(struct ehca_shca *shca, int is_irq)
531{ 531{
532 struct ehca_eq *eq = &shca->eq; 532 struct ehca_eq *eq = &shca->eq;
533 struct ehca_eqe_cache_entry *eqe_cache = eq->eqe_cache; 533 struct ehca_eqe_cache_entry *eqe_cache = eq->eqe_cache;
534 u64 eqe_value; 534 u64 eqe_value, ret;
535 unsigned long flags; 535 unsigned long flags;
536 int eqe_cnt, i; 536 int eqe_cnt, i;
537 int eq_empty = 0; 537 int eq_empty = 0;
@@ -583,8 +583,13 @@ void ehca_process_eq(struct ehca_shca *shca, int is_irq)
583 ehca_dbg(&shca->ib_device, 583 ehca_dbg(&shca->ib_device,
584 "No eqe found for irq event"); 584 "No eqe found for irq event");
585 goto unlock_irq_spinlock; 585 goto unlock_irq_spinlock;
586 } else if (!is_irq) 586 } else if (!is_irq) {
587 ret = hipz_h_eoi(eq->ist);
588 if (ret != H_SUCCESS)
589 ehca_err(&shca->ib_device,
590 "bad return code EOI -rc = %ld\n", ret);
587 ehca_dbg(&shca->ib_device, "deadman found %x eqe", eqe_cnt); 591 ehca_dbg(&shca->ib_device, "deadman found %x eqe", eqe_cnt);
592 }
588 if (unlikely(eqe_cnt == EHCA_EQE_CACHE_SIZE)) 593 if (unlikely(eqe_cnt == EHCA_EQE_CACHE_SIZE))
589 ehca_dbg(&shca->ib_device, "too many eqes for one irq event"); 594 ehca_dbg(&shca->ib_device, "too many eqes for one irq event");
590 /* enable irq for new packets */ 595 /* enable irq for new packets */
diff --git a/drivers/infiniband/hw/ehca/hcp_if.c b/drivers/infiniband/hw/ehca/hcp_if.c
index 5245e13c3a30..415d3a465de6 100644
--- a/drivers/infiniband/hw/ehca/hcp_if.c
+++ b/drivers/infiniband/hw/ehca/hcp_if.c
@@ -933,3 +933,13 @@ u64 hipz_h_error_data(const struct ipz_adapter_handle adapter_handle,
933 r_cb, 933 r_cb,
934 0, 0, 0, 0); 934 0, 0, 0, 0);
935} 935}
936
937u64 hipz_h_eoi(int irq)
938{
939 unsigned long xirr;
940
941 iosync();
942 xirr = (0xffULL << 24) | irq;
943
944 return plpar_hcall_norets(H_EOI, xirr);
945}
diff --git a/drivers/infiniband/hw/ehca/hcp_if.h b/drivers/infiniband/hw/ehca/hcp_if.h
index 60ce02b70663..2c3c6e0ea5c2 100644
--- a/drivers/infiniband/hw/ehca/hcp_if.h
+++ b/drivers/infiniband/hw/ehca/hcp_if.h
@@ -260,5 +260,6 @@ u64 hipz_h_error_data(const struct ipz_adapter_handle adapter_handle,
260 const u64 ressource_handle, 260 const u64 ressource_handle,
261 void *rblock, 261 void *rblock,
262 unsigned long *byte_count); 262 unsigned long *byte_count);
263u64 hipz_h_eoi(int irq);
263 264
264#endif /* __HCP_IF_H__ */ 265#endif /* __HCP_IF_H__ */