aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw
diff options
context:
space:
mode:
authorRalph Campbell <ralph.campbell@qlogic.com>2007-09-19 19:47:31 -0400
committerRoland Dreier <rolandd@cisco.com>2007-10-10 00:01:38 -0400
commit49739b3e24a10d819d3167a1c5b319d0b1186245 (patch)
tree487d4df80efa73d31ab414564021503d289b6b3f /drivers/infiniband/hw
parent6a733cdc71b7aa8107caa57f2a16629aa731242a (diff)
IB/ipath: Fix IB_EVENT_PORT_ERR event
The link state event calls were being generated when the SM told the SMA to change link states. This works for IB_EVENT_PORT_ACTIVE but not if the link goes down and stays down. The fix is to generate event calls from the interrupt handler when the HW link state changes. Signed-off-by: Ralph Campbell <ralph.campbell@qlogic.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/hw')
-rw-r--r--drivers/infiniband/hw/ipath/ipath_driver.c2
-rw-r--r--drivers/infiniband/hw/ipath/ipath_intr.c17
-rw-r--r--drivers/infiniband/hw/ipath/ipath_kernel.h2
-rw-r--r--drivers/infiniband/hw/ipath/ipath_mad.c10
-rw-r--r--drivers/infiniband/hw/ipath/ipath_verbs.c12
5 files changed, 31 insertions, 12 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c
index 44784d049b71..1f152ded1e3c 100644
--- a/drivers/infiniband/hw/ipath/ipath_driver.c
+++ b/drivers/infiniband/hw/ipath/ipath_driver.c
@@ -2086,6 +2086,8 @@ void ipath_shutdown_device(struct ipath_devdata *dd)
2086 INFINIPATH_IBCC_LINKINITCMD_SHIFT); 2086 INFINIPATH_IBCC_LINKINITCMD_SHIFT);
2087 ipath_cancel_sends(dd, 0); 2087 ipath_cancel_sends(dd, 0);
2088 2088
2089 signal_ib_event(dd, IB_EVENT_PORT_ERR);
2090
2089 /* disable IBC */ 2091 /* disable IBC */
2090 dd->ipath_control &= ~INFINIPATH_C_LINKENABLE; 2092 dd->ipath_control &= ~INFINIPATH_C_LINKENABLE;
2091 ipath_write_kreg(dd, dd->ipath_kregs->kr_control, 2093 ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
diff --git a/drivers/infiniband/hw/ipath/ipath_intr.c b/drivers/infiniband/hw/ipath/ipath_intr.c
index 801a20d06de6..6a5dd5cd773d 100644
--- a/drivers/infiniband/hw/ipath/ipath_intr.c
+++ b/drivers/infiniband/hw/ipath/ipath_intr.c
@@ -275,6 +275,16 @@ static char *ib_linkstate(u32 linkstate)
275 return ret; 275 return ret;
276} 276}
277 277
278void signal_ib_event(struct ipath_devdata *dd, enum ib_event_type ev)
279{
280 struct ib_event event;
281
282 event.device = &dd->verbs_dev->ibdev;
283 event.element.port_num = 1;
284 event.event = ev;
285 ib_dispatch_event(&event);
286}
287
278static void handle_e_ibstatuschanged(struct ipath_devdata *dd, 288static void handle_e_ibstatuschanged(struct ipath_devdata *dd,
279 ipath_err_t errs, int noprint) 289 ipath_err_t errs, int noprint)
280{ 290{
@@ -373,6 +383,8 @@ static void handle_e_ibstatuschanged(struct ipath_devdata *dd,
373 dd->ipath_ibpollcnt = 0; /* some state other than 2 or 3 */ 383 dd->ipath_ibpollcnt = 0; /* some state other than 2 or 3 */
374 ipath_stats.sps_iblink++; 384 ipath_stats.sps_iblink++;
375 if (ltstate != INFINIPATH_IBCS_LT_STATE_LINKUP) { 385 if (ltstate != INFINIPATH_IBCS_LT_STATE_LINKUP) {
386 if (dd->ipath_flags & IPATH_LINKACTIVE)
387 signal_ib_event(dd, IB_EVENT_PORT_ERR);
376 dd->ipath_flags |= IPATH_LINKDOWN; 388 dd->ipath_flags |= IPATH_LINKDOWN;
377 dd->ipath_flags &= ~(IPATH_LINKUNK | IPATH_LINKINIT 389 dd->ipath_flags &= ~(IPATH_LINKUNK | IPATH_LINKINIT
378 | IPATH_LINKACTIVE | 390 | IPATH_LINKACTIVE |
@@ -405,7 +417,10 @@ static void handle_e_ibstatuschanged(struct ipath_devdata *dd,
405 *dd->ipath_statusp |= 417 *dd->ipath_statusp |=
406 IPATH_STATUS_IB_READY | IPATH_STATUS_IB_CONF; 418 IPATH_STATUS_IB_READY | IPATH_STATUS_IB_CONF;
407 dd->ipath_f_setextled(dd, lstate, ltstate); 419 dd->ipath_f_setextled(dd, lstate, ltstate);
420 signal_ib_event(dd, IB_EVENT_PORT_ACTIVE);
408 } else if ((val & IPATH_IBSTATE_MASK) == IPATH_IBSTATE_INIT) { 421 } else if ((val & IPATH_IBSTATE_MASK) == IPATH_IBSTATE_INIT) {
422 if (dd->ipath_flags & IPATH_LINKACTIVE)
423 signal_ib_event(dd, IB_EVENT_PORT_ERR);
409 /* 424 /*
410 * set INIT and DOWN. Down is checked by most of the other 425 * set INIT and DOWN. Down is checked by most of the other
411 * code, but INIT is useful to know in a few places. 426 * code, but INIT is useful to know in a few places.
@@ -418,6 +433,8 @@ static void handle_e_ibstatuschanged(struct ipath_devdata *dd,
418 | IPATH_STATUS_IB_READY); 433 | IPATH_STATUS_IB_READY);
419 dd->ipath_f_setextled(dd, lstate, ltstate); 434 dd->ipath_f_setextled(dd, lstate, ltstate);
420 } else if ((val & IPATH_IBSTATE_MASK) == IPATH_IBSTATE_ARM) { 435 } else if ((val & IPATH_IBSTATE_MASK) == IPATH_IBSTATE_ARM) {
436 if (dd->ipath_flags & IPATH_LINKACTIVE)
437 signal_ib_event(dd, IB_EVENT_PORT_ERR);
421 dd->ipath_flags |= IPATH_LINKARMED; 438 dd->ipath_flags |= IPATH_LINKARMED;
422 dd->ipath_flags &= 439 dd->ipath_flags &=
423 ~(IPATH_LINKUNK | IPATH_LINKDOWN | IPATH_LINKINIT | 440 ~(IPATH_LINKUNK | IPATH_LINKDOWN | IPATH_LINKINIT |
diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h
index 872fb36703d9..8786dd7922e4 100644
--- a/drivers/infiniband/hw/ipath/ipath_kernel.h
+++ b/drivers/infiniband/hw/ipath/ipath_kernel.h
@@ -42,6 +42,7 @@
42#include <linux/pci.h> 42#include <linux/pci.h>
43#include <linux/dma-mapping.h> 43#include <linux/dma-mapping.h>
44#include <asm/io.h> 44#include <asm/io.h>
45#include <rdma/ib_verbs.h>
45 46
46#include "ipath_common.h" 47#include "ipath_common.h"
47#include "ipath_debug.h" 48#include "ipath_debug.h"
@@ -775,6 +776,7 @@ void ipath_get_eeprom_info(struct ipath_devdata *);
775int ipath_update_eeprom_log(struct ipath_devdata *dd); 776int ipath_update_eeprom_log(struct ipath_devdata *dd);
776void ipath_inc_eeprom_err(struct ipath_devdata *dd, u32 eidx, u32 incr); 777void ipath_inc_eeprom_err(struct ipath_devdata *dd, u32 eidx, u32 incr);
777u64 ipath_snap_cntr(struct ipath_devdata *, ipath_creg); 778u64 ipath_snap_cntr(struct ipath_devdata *, ipath_creg);
779void signal_ib_event(struct ipath_devdata *dd, enum ib_event_type ev);
778 780
779/* 781/*
780 * Set LED override, only the two LSBs have "public" meaning, but 782 * Set LED override, only the two LSBs have "public" meaning, but
diff --git a/drivers/infiniband/hw/ipath/ipath_mad.c b/drivers/infiniband/hw/ipath/ipath_mad.c
index 8f152167208a..0ae3a7c3f86e 100644
--- a/drivers/infiniband/hw/ipath/ipath_mad.c
+++ b/drivers/infiniband/hw/ipath/ipath_mad.c
@@ -570,26 +570,16 @@ static int recv_subn_set_portinfo(struct ib_smp *smp,
570 else 570 else
571 goto err; 571 goto err;
572 ipath_set_linkstate(dd, lstate); 572 ipath_set_linkstate(dd, lstate);
573 if (flags & IPATH_LINKACTIVE) {
574 event.event = IB_EVENT_PORT_ERR;
575 ib_dispatch_event(&event);
576 }
577 break; 573 break;
578 case IB_PORT_ARMED: 574 case IB_PORT_ARMED:
579 if (!(flags & (IPATH_LINKINIT | IPATH_LINKACTIVE))) 575 if (!(flags & (IPATH_LINKINIT | IPATH_LINKACTIVE)))
580 break; 576 break;
581 ipath_set_linkstate(dd, IPATH_IB_LINKARM); 577 ipath_set_linkstate(dd, IPATH_IB_LINKARM);
582 if (flags & IPATH_LINKACTIVE) {
583 event.event = IB_EVENT_PORT_ERR;
584 ib_dispatch_event(&event);
585 }
586 break; 578 break;
587 case IB_PORT_ACTIVE: 579 case IB_PORT_ACTIVE:
588 if (!(flags & IPATH_LINKARMED)) 580 if (!(flags & IPATH_LINKARMED))
589 break; 581 break;
590 ipath_set_linkstate(dd, IPATH_IB_LINKACTIVE); 582 ipath_set_linkstate(dd, IPATH_IB_LINKACTIVE);
591 event.event = IB_EVENT_PORT_ACTIVE;
592 ib_dispatch_event(&event);
593 break; 583 break;
594 default: 584 default:
595 /* XXX We have already partially updated our state! */ 585 /* XXX We have already partially updated our state! */
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.c b/drivers/infiniband/hw/ipath/ipath_verbs.c
index 13aba3d40543..74f77e7c2c1b 100644
--- a/drivers/infiniband/hw/ipath/ipath_verbs.c
+++ b/drivers/infiniband/hw/ipath/ipath_verbs.c
@@ -948,6 +948,7 @@ bail:
948int ipath_verbs_send(struct ipath_qp *qp, struct ipath_ib_header *hdr, 948int ipath_verbs_send(struct ipath_qp *qp, struct ipath_ib_header *hdr,
949 u32 hdrwords, struct ipath_sge_state *ss, u32 len) 949 u32 hdrwords, struct ipath_sge_state *ss, u32 len)
950{ 950{
951 struct ipath_devdata *dd = to_idev(qp->ibqp.device)->dd;
951 u32 plen; 952 u32 plen;
952 int ret; 953 int ret;
953 u32 dwords = (len + 3) >> 2; 954 u32 dwords = (len + 3) >> 2;
@@ -955,8 +956,15 @@ int ipath_verbs_send(struct ipath_qp *qp, struct ipath_ib_header *hdr,
955 /* +1 is for the qword padding of pbc */ 956 /* +1 is for the qword padding of pbc */
956 plen = hdrwords + dwords + 1; 957 plen = hdrwords + dwords + 1;
957 958
958 ret = ipath_verbs_send_pio(qp, (u32 *) hdr, hdrwords, 959 /* Drop non-VL15 packets if we are not in the active state */
959 ss, len, plen, dwords); 960 if (!(dd->ipath_flags & IPATH_LINKACTIVE) &&
961 qp->ibqp.qp_type != IB_QPT_SMI) {
962 if (qp->s_wqe)
963 ipath_send_complete(qp, qp->s_wqe, IB_WC_SUCCESS);
964 ret = 0;
965 } else
966 ret = ipath_verbs_send_pio(qp, (u32 *) hdr, hdrwords,
967 ss, len, plen, dwords);
960 968
961 return ret; 969 return ret;
962} 970}