提交 49739b3e 编写于 作者: R Ralph Campbell 提交者: Roland Dreier

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: NRalph Campbell <ralph.campbell@qlogic.com>
Signed-off-by: NRoland Dreier <rolandd@cisco.com>
上级 6a733cdc
...@@ -2086,6 +2086,8 @@ void ipath_shutdown_device(struct ipath_devdata *dd) ...@@ -2086,6 +2086,8 @@ void ipath_shutdown_device(struct ipath_devdata *dd)
INFINIPATH_IBCC_LINKINITCMD_SHIFT); INFINIPATH_IBCC_LINKINITCMD_SHIFT);
ipath_cancel_sends(dd, 0); ipath_cancel_sends(dd, 0);
signal_ib_event(dd, IB_EVENT_PORT_ERR);
/* disable IBC */ /* disable IBC */
dd->ipath_control &= ~INFINIPATH_C_LINKENABLE; dd->ipath_control &= ~INFINIPATH_C_LINKENABLE;
ipath_write_kreg(dd, dd->ipath_kregs->kr_control, ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
......
...@@ -275,6 +275,16 @@ static char *ib_linkstate(u32 linkstate) ...@@ -275,6 +275,16 @@ static char *ib_linkstate(u32 linkstate)
return ret; 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, static void handle_e_ibstatuschanged(struct ipath_devdata *dd,
ipath_err_t errs, int noprint) ipath_err_t errs, int noprint)
{ {
...@@ -373,6 +383,8 @@ static void handle_e_ibstatuschanged(struct ipath_devdata *dd, ...@@ -373,6 +383,8 @@ static void handle_e_ibstatuschanged(struct ipath_devdata *dd,
dd->ipath_ibpollcnt = 0; /* some state other than 2 or 3 */ dd->ipath_ibpollcnt = 0; /* some state other than 2 or 3 */
ipath_stats.sps_iblink++; ipath_stats.sps_iblink++;
if (ltstate != INFINIPATH_IBCS_LT_STATE_LINKUP) { 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_LINKDOWN;
dd->ipath_flags &= ~(IPATH_LINKUNK | IPATH_LINKINIT dd->ipath_flags &= ~(IPATH_LINKUNK | IPATH_LINKINIT
| IPATH_LINKACTIVE | | IPATH_LINKACTIVE |
...@@ -405,7 +417,10 @@ static void handle_e_ibstatuschanged(struct ipath_devdata *dd, ...@@ -405,7 +417,10 @@ static void handle_e_ibstatuschanged(struct ipath_devdata *dd,
*dd->ipath_statusp |= *dd->ipath_statusp |=
IPATH_STATUS_IB_READY | IPATH_STATUS_IB_CONF; IPATH_STATUS_IB_READY | IPATH_STATUS_IB_CONF;
dd->ipath_f_setextled(dd, lstate, ltstate); dd->ipath_f_setextled(dd, lstate, ltstate);
signal_ib_event(dd, IB_EVENT_PORT_ACTIVE);
} else if ((val & IPATH_IBSTATE_MASK) == IPATH_IBSTATE_INIT) { } 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 * set INIT and DOWN. Down is checked by most of the other
* code, but INIT is useful to know in a few places. * 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,6 +433,8 @@ static void handle_e_ibstatuschanged(struct ipath_devdata *dd,
| IPATH_STATUS_IB_READY); | IPATH_STATUS_IB_READY);
dd->ipath_f_setextled(dd, lstate, ltstate); dd->ipath_f_setextled(dd, lstate, ltstate);
} else if ((val & IPATH_IBSTATE_MASK) == IPATH_IBSTATE_ARM) { } 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_LINKARMED;
dd->ipath_flags &= dd->ipath_flags &=
~(IPATH_LINKUNK | IPATH_LINKDOWN | IPATH_LINKINIT | ~(IPATH_LINKUNK | IPATH_LINKDOWN | IPATH_LINKINIT |
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <asm/io.h> #include <asm/io.h>
#include <rdma/ib_verbs.h>
#include "ipath_common.h" #include "ipath_common.h"
#include "ipath_debug.h" #include "ipath_debug.h"
...@@ -775,6 +776,7 @@ void ipath_get_eeprom_info(struct ipath_devdata *); ...@@ -775,6 +776,7 @@ void ipath_get_eeprom_info(struct ipath_devdata *);
int ipath_update_eeprom_log(struct ipath_devdata *dd); int ipath_update_eeprom_log(struct ipath_devdata *dd);
void ipath_inc_eeprom_err(struct ipath_devdata *dd, u32 eidx, u32 incr); void ipath_inc_eeprom_err(struct ipath_devdata *dd, u32 eidx, u32 incr);
u64 ipath_snap_cntr(struct ipath_devdata *, ipath_creg); 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 * Set LED override, only the two LSBs have "public" meaning, but
......
...@@ -570,26 +570,16 @@ static int recv_subn_set_portinfo(struct ib_smp *smp, ...@@ -570,26 +570,16 @@ static int recv_subn_set_portinfo(struct ib_smp *smp,
else else
goto err; goto err;
ipath_set_linkstate(dd, lstate); ipath_set_linkstate(dd, lstate);
if (flags & IPATH_LINKACTIVE) {
event.event = IB_EVENT_PORT_ERR;
ib_dispatch_event(&event);
}
break; break;
case IB_PORT_ARMED: case IB_PORT_ARMED:
if (!(flags & (IPATH_LINKINIT | IPATH_LINKACTIVE))) if (!(flags & (IPATH_LINKINIT | IPATH_LINKACTIVE)))
break; break;
ipath_set_linkstate(dd, IPATH_IB_LINKARM); ipath_set_linkstate(dd, IPATH_IB_LINKARM);
if (flags & IPATH_LINKACTIVE) {
event.event = IB_EVENT_PORT_ERR;
ib_dispatch_event(&event);
}
break; break;
case IB_PORT_ACTIVE: case IB_PORT_ACTIVE:
if (!(flags & IPATH_LINKARMED)) if (!(flags & IPATH_LINKARMED))
break; break;
ipath_set_linkstate(dd, IPATH_IB_LINKACTIVE); ipath_set_linkstate(dd, IPATH_IB_LINKACTIVE);
event.event = IB_EVENT_PORT_ACTIVE;
ib_dispatch_event(&event);
break; break;
default: default:
/* XXX We have already partially updated our state! */ /* XXX We have already partially updated our state! */
......
...@@ -948,6 +948,7 @@ static int ipath_verbs_send_pio(struct ipath_qp *qp, u32 *hdr, u32 hdrwords, ...@@ -948,6 +948,7 @@ 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, int ipath_verbs_send(struct ipath_qp *qp, struct ipath_ib_header *hdr,
u32 hdrwords, struct ipath_sge_state *ss, u32 len) u32 hdrwords, struct ipath_sge_state *ss, u32 len)
{ {
struct ipath_devdata *dd = to_idev(qp->ibqp.device)->dd;
u32 plen; u32 plen;
int ret; int ret;
u32 dwords = (len + 3) >> 2; u32 dwords = (len + 3) >> 2;
...@@ -955,8 +956,15 @@ int ipath_verbs_send(struct ipath_qp *qp, struct ipath_ib_header *hdr, ...@@ -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 */ /* +1 is for the qword padding of pbc */
plen = hdrwords + dwords + 1; plen = hdrwords + dwords + 1;
ret = ipath_verbs_send_pio(qp, (u32 *) hdr, hdrwords, /* Drop non-VL15 packets if we are not in the active state */
ss, len, plen, dwords); 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; return ret;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册