Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=49739b3e24a10d819d3167a1c5b319d0b1186245
Commit:     49739b3e24a10d819d3167a1c5b319d0b1186245
Parent:     6a733cdc71b7aa8107caa57f2a16629aa731242a
Author:     Ralph Campbell <[EMAIL PROTECTED]>
AuthorDate: Wed Sep 19 16:47:31 2007 -0700
Committer:  Roland Dreier <[EMAIL PROTECTED]>
CommitDate: Tue Oct 9 21:01:38 2007 -0700

    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 <[EMAIL PROTECTED]>
    Signed-off-by: Roland Dreier <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ipath/ipath_driver.c |    2 ++
 drivers/infiniband/hw/ipath/ipath_intr.c   |   17 +++++++++++++++++
 drivers/infiniband/hw/ipath/ipath_kernel.h |    2 ++
 drivers/infiniband/hw/ipath/ipath_mad.c    |   10 ----------
 drivers/infiniband/hw/ipath/ipath_verbs.c  |   12 ++++++++++--
 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 44784d0..1f152de 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)
                            INFINIPATH_IBCC_LINKINITCMD_SHIFT);
        ipath_cancel_sends(dd, 0);
 
+       signal_ib_event(dd, IB_EVENT_PORT_ERR);
+
        /* disable IBC */
        dd->ipath_control &= ~INFINIPATH_C_LINKENABLE;
        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 801a20d..6a5dd5c 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)
        return ret;
 }
 
+void signal_ib_event(struct ipath_devdata *dd, enum ib_event_type ev)
+{
+       struct ib_event event;
+
+       event.device = &dd->verbs_dev->ibdev;
+       event.element.port_num = 1;
+       event.event = ev;
+       ib_dispatch_event(&event);
+}
+
 static void handle_e_ibstatuschanged(struct ipath_devdata *dd,
                                     ipath_err_t errs, int noprint)
 {
@@ -373,6 +383,8 @@ static void handle_e_ibstatuschanged(struct ipath_devdata 
*dd,
        dd->ipath_ibpollcnt = 0;        /* some state other than 2 or 3 */
        ipath_stats.sps_iblink++;
        if (ltstate != INFINIPATH_IBCS_LT_STATE_LINKUP) {
+               if (dd->ipath_flags & IPATH_LINKACTIVE)
+                       signal_ib_event(dd, IB_EVENT_PORT_ERR);
                dd->ipath_flags |= IPATH_LINKDOWN;
                dd->ipath_flags &= ~(IPATH_LINKUNK | IPATH_LINKINIT
                                     | IPATH_LINKACTIVE |
@@ -405,7 +417,10 @@ static void handle_e_ibstatuschanged(struct ipath_devdata 
*dd,
                *dd->ipath_statusp |=
                        IPATH_STATUS_IB_READY | IPATH_STATUS_IB_CONF;
                dd->ipath_f_setextled(dd, lstate, ltstate);
+               signal_ib_event(dd, IB_EVENT_PORT_ACTIVE);
        } else if ((val & IPATH_IBSTATE_MASK) == IPATH_IBSTATE_INIT) {
+               if (dd->ipath_flags & IPATH_LINKACTIVE)
+                       signal_ib_event(dd, IB_EVENT_PORT_ERR);
                /*
                 * set INIT and DOWN.  Down is checked by most of the other
                 * code, but INIT is useful to know in a few places.
@@ -418,6 +433,8 @@ static void handle_e_ibstatuschanged(struct ipath_devdata 
*dd,
                                        | IPATH_STATUS_IB_READY);
                dd->ipath_f_setextled(dd, lstate, ltstate);
        } else if ((val & IPATH_IBSTATE_MASK) == IPATH_IBSTATE_ARM) {
+               if (dd->ipath_flags & IPATH_LINKACTIVE)
+                       signal_ib_event(dd, IB_EVENT_PORT_ERR);
                dd->ipath_flags |= IPATH_LINKARMED;
                dd->ipath_flags &=
                        ~(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 872fb36..8786dd7 100644
--- a/drivers/infiniband/hw/ipath/ipath_kernel.h
+++ b/drivers/infiniband/hw/ipath/ipath_kernel.h
@@ -42,6 +42,7 @@
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
 #include <asm/io.h>
+#include <rdma/ib_verbs.h>
 
 #include "ipath_common.h"
 #include "ipath_debug.h"
@@ -775,6 +776,7 @@ void ipath_get_eeprom_info(struct ipath_devdata *);
 int ipath_update_eeprom_log(struct ipath_devdata *dd);
 void ipath_inc_eeprom_err(struct ipath_devdata *dd, u32 eidx, u32 incr);
 u64 ipath_snap_cntr(struct ipath_devdata *, ipath_creg);
+void signal_ib_event(struct ipath_devdata *dd, enum ib_event_type ev);
 
 /*
  * 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 8f15216..0ae3a7c 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,
                else
                        goto err;
                ipath_set_linkstate(dd, lstate);
-               if (flags & IPATH_LINKACTIVE) {
-                       event.event = IB_EVENT_PORT_ERR;
-                       ib_dispatch_event(&event);
-               }
                break;
        case IB_PORT_ARMED:
                if (!(flags & (IPATH_LINKINIT | IPATH_LINKACTIVE)))
                        break;
                ipath_set_linkstate(dd, IPATH_IB_LINKARM);
-               if (flags & IPATH_LINKACTIVE) {
-                       event.event = IB_EVENT_PORT_ERR;
-                       ib_dispatch_event(&event);
-               }
                break;
        case IB_PORT_ACTIVE:
                if (!(flags & IPATH_LINKARMED))
                        break;
                ipath_set_linkstate(dd, IPATH_IB_LINKACTIVE);
-               event.event = IB_EVENT_PORT_ACTIVE;
-               ib_dispatch_event(&event);
                break;
        default:
                /* 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 13aba3d..74f77e7 100644
--- a/drivers/infiniband/hw/ipath/ipath_verbs.c
+++ b/drivers/infiniband/hw/ipath/ipath_verbs.c
@@ -948,6 +948,7 @@ bail:
 int ipath_verbs_send(struct ipath_qp *qp, struct ipath_ib_header *hdr,
                     u32 hdrwords, struct ipath_sge_state *ss, u32 len)
 {
+       struct ipath_devdata *dd = to_idev(qp->ibqp.device)->dd;
        u32 plen;
        int ret;
        u32 dwords = (len + 3) >> 2;
@@ -955,8 +956,15 @@ int ipath_verbs_send(struct ipath_qp *qp, struct 
ipath_ib_header *hdr,
        /* +1 is for the qword padding of pbc */
        plen = hdrwords + dwords + 1;
 
-       ret = ipath_verbs_send_pio(qp, (u32 *) hdr, hdrwords,
-                                  ss, len, plen, dwords);
+       /* Drop non-VL15 packets if we are not in the active state */
+       if (!(dd->ipath_flags & IPATH_LINKACTIVE) &&
+           qp->ibqp.qp_type != IB_QPT_SMI) {
+               if (qp->s_wqe)
+                       ipath_send_complete(qp, qp->s_wqe, IB_WC_SUCCESS);
+               ret = 0;
+       } else
+               ret = ipath_verbs_send_pio(qp, (u32 *) hdr, hdrwords,
+                                          ss, len, plen, dwords);
 
        return ret;
 }
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to