Skip to content

Commit

Permalink
IB/ipath: Fix IB_EVENT_PORT_ERR event
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Ralph Campbell authored and Roland Dreier committed Oct 10, 2007
1 parent 6a733cd commit 49739b3
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 12 deletions.
2 changes: 2 additions & 0 deletions drivers/infiniband/hw/ipath/ipath_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
17 changes: 17 additions & 0 deletions drivers/infiniband/hw/ipath/ipath_intr.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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 |
Expand Down Expand Up @@ -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.
Expand All @@ -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 |
Expand Down
2 changes: 2 additions & 0 deletions drivers/infiniband/hw/ipath/ipath_kernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand Down
10 changes: 0 additions & 10 deletions drivers/infiniband/hw/ipath/ipath_mad.c
Original file line number Diff line number Diff line change
Expand Up @@ -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! */
Expand Down
12 changes: 10 additions & 2 deletions drivers/infiniband/hw/ipath/ipath_verbs.c
Original file line number Diff line number Diff line change
Expand Up @@ -948,15 +948,23 @@ static int ipath_verbs_send_pio(struct ipath_qp *qp, u32 *hdr, u32 hdrwords,
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;

/* +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;
}
Expand Down

0 comments on commit 49739b3

Please sign in to comment.