cxgbe/iw_cxgbe: Add an async callback to notify iw_cxgbe in case of a
fatal error. Submitted by: Krishnamraju Eraparaju @ Chelsio MFC after: 2 weeks Sponsored by: Chelsio Communications
This commit is contained in:
parent
a918433b8a
commit
b0dede77b1
@ -830,6 +830,7 @@ struct adapter {
|
||||
int sc_do_rxcopy;
|
||||
|
||||
struct taskqueue *tq[MAX_NCHAN]; /* General purpose taskqueues */
|
||||
struct task async_event_task;
|
||||
struct port_info *port[MAX_NPORTS];
|
||||
uint8_t chan_map[MAX_NCHAN]; /* channel -> port */
|
||||
|
||||
|
@ -1085,7 +1085,7 @@ c4iw_so_upcall(struct socket *so, void *arg, int waitflag)
|
||||
* Wake up any threads waiting in rdma_init()/rdma_fini(),
|
||||
* with locks held.
|
||||
*/
|
||||
if (so->so_error)
|
||||
if (so->so_error || (ep->com.dev->rdev.flags & T4_FATAL_ERROR))
|
||||
c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET);
|
||||
add_ep_to_req_list(ep, C4IW_EVENT_SOCKET);
|
||||
|
||||
@ -2700,6 +2700,11 @@ c4iw_create_listen(struct iw_cm_id *cm_id, int backlog)
|
||||
|
||||
CTR3(KTR_IW_CXGBE, "%s: cm_id %p, backlog %s", __func__, cm_id,
|
||||
backlog);
|
||||
if (c4iw_fatal_error(&dev->rdev)) {
|
||||
CTR2(KTR_IW_CXGBE, "%s: cm_id %p, fatal error", __func__,
|
||||
cm_id);
|
||||
return -EIO;
|
||||
}
|
||||
lep = alloc_ep(sizeof(*lep), GFP_KERNEL);
|
||||
lep->com.cm_id = cm_id;
|
||||
ref_cm_id(&lep->com);
|
||||
@ -2800,7 +2805,6 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp)
|
||||
{
|
||||
int ret = 0;
|
||||
int close = 0;
|
||||
int fatal = 0;
|
||||
struct c4iw_rdev *rdev;
|
||||
|
||||
|
||||
@ -2809,12 +2813,14 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp)
|
||||
rdev = &ep->com.dev->rdev;
|
||||
|
||||
if (c4iw_fatal_error(rdev)) {
|
||||
|
||||
CTR2(KTR_IW_CXGBE, "%s:ced1 %p", __func__, ep);
|
||||
fatal = 1;
|
||||
CTR3(KTR_IW_CXGBE, "%s:ced1 fatal error %p %s", __func__, ep,
|
||||
states[ep->com.state]);
|
||||
if (ep->com.state != DEAD) {
|
||||
send_abort(ep);
|
||||
ep->com.state = DEAD;
|
||||
}
|
||||
close_complete_upcall(ep, -ECONNRESET);
|
||||
send_abort(ep);
|
||||
ep->com.state = DEAD;
|
||||
return ECONNRESET;
|
||||
}
|
||||
CTR3(KTR_IW_CXGBE, "%s:ced2 %p %s", __func__, ep,
|
||||
states[ep->com.state]);
|
||||
@ -2877,9 +2883,7 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp)
|
||||
CTR2(KTR_IW_CXGBE, "%s:ced4 %p", __func__, ep);
|
||||
set_bit(EP_DISC_ABORT, &ep->com.history);
|
||||
close_complete_upcall(ep, -ECONNRESET);
|
||||
ret = send_abort(ep);
|
||||
if (ret)
|
||||
fatal = 1;
|
||||
send_abort(ep);
|
||||
} else {
|
||||
|
||||
CTR2(KTR_IW_CXGBE, "%s:ced5 %p", __func__, ep);
|
||||
@ -2889,33 +2893,28 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp)
|
||||
ep->com.state = MORIBUND;
|
||||
|
||||
CURVNET_SET(ep->com.so->so_vnet);
|
||||
sodisconnect(ep->com.so);
|
||||
ret = sodisconnect(ep->com.so);
|
||||
CURVNET_RESTORE();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (fatal) {
|
||||
set_bit(EP_DISC_FAIL, &ep->com.history);
|
||||
if (!abrupt) {
|
||||
STOP_EP_TIMER(ep);
|
||||
close_complete_upcall(ep, -EIO);
|
||||
}
|
||||
if (ep->com.qp) {
|
||||
struct c4iw_qp_attributes attrs = {0};
|
||||
|
||||
attrs.next_state = C4IW_QP_STATE_ERROR;
|
||||
ret = c4iw_modify_qp(ep->com.dev, ep->com.qp,
|
||||
C4IW_QP_ATTR_NEXT_STATE,
|
||||
&attrs, 1);
|
||||
if (ret) {
|
||||
CTR2(KTR_IW_CXGBE, "%s:ced7 %p", __func__, ep);
|
||||
printf("%s - qp <- error failed!\n", __func__);
|
||||
CTR2(KTR_IW_CXGBE, "%s:ced6 %p", __func__, ep);
|
||||
STOP_EP_TIMER(ep);
|
||||
send_abort(ep);
|
||||
ep->com.state = DEAD;
|
||||
close_complete_upcall(ep, -ECONNRESET);
|
||||
set_bit(EP_DISC_FAIL, &ep->com.history);
|
||||
if (ep->com.qp) {
|
||||
struct c4iw_qp_attributes attrs = {0};
|
||||
|
||||
attrs.next_state = C4IW_QP_STATE_ERROR;
|
||||
ret = c4iw_modify_qp(
|
||||
ep->com.dev, ep->com.qp,
|
||||
C4IW_QP_ATTR_NEXT_STATE,
|
||||
&attrs, 1);
|
||||
CTR3(KTR_IW_CXGBE, "%s:ced7 %p ret %d",
|
||||
__func__, ep, ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
release_ep_resources(ep);
|
||||
ep->com.state = DEAD;
|
||||
CTR2(KTR_IW_CXGBE, "%s:ced6 %p", __func__, ep);
|
||||
}
|
||||
c4iw_put_ep(&ep->com);
|
||||
CTR2(KTR_IW_CXGBE, "%s:cedE %p", __func__, ep);
|
||||
|
@ -261,11 +261,13 @@ static int c4iw_mod_load(void);
|
||||
static int c4iw_mod_unload(void);
|
||||
static int c4iw_activate(struct adapter *);
|
||||
static int c4iw_deactivate(struct adapter *);
|
||||
static void c4iw_async_event(struct adapter *);
|
||||
|
||||
static struct uld_info c4iw_uld_info = {
|
||||
.uld_id = ULD_IWARP,
|
||||
.activate = c4iw_activate,
|
||||
.deactivate = c4iw_deactivate,
|
||||
.async_event = c4iw_async_event,
|
||||
};
|
||||
|
||||
static int
|
||||
@ -326,6 +328,23 @@ c4iw_deactivate(struct adapter *sc)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
c4iw_async_event(struct adapter *sc)
|
||||
{
|
||||
struct c4iw_dev *iwsc = sc->iwarp_softc;
|
||||
|
||||
if (iwsc) {
|
||||
struct ib_event event = {0};
|
||||
|
||||
device_printf(sc->dev,
|
||||
"iWARP driver received FATAL ERROR event.\n");
|
||||
iwsc->rdev.flags |= T4_FATAL_ERROR;
|
||||
event.event = IB_EVENT_DEVICE_FATAL;
|
||||
event.device = &iwsc->ibdev;
|
||||
ib_dispatch_event(&event);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
c4iw_activate_all(struct adapter *sc, void *arg __unused)
|
||||
{
|
||||
|
@ -228,6 +228,7 @@ struct uld_info {
|
||||
int uld_id;
|
||||
int (*activate)(struct adapter *);
|
||||
int (*deactivate)(struct adapter *);
|
||||
void (*async_event)(struct adapter *);
|
||||
};
|
||||
|
||||
struct tom_tunables {
|
||||
|
@ -758,6 +758,7 @@ static int read_i2c(struct adapter *, struct t4_i2c_data *);
|
||||
static int clear_stats(struct adapter *, u_int);
|
||||
#ifdef TCP_OFFLOAD
|
||||
static int toe_capability(struct vi_info *, int);
|
||||
static void t4_async_event(void *, int);
|
||||
#endif
|
||||
static int mod_event(module_t, int, void *);
|
||||
static int notify_siblings(device_t, int);
|
||||
@ -1063,6 +1064,10 @@ t4_attach(device_t dev)
|
||||
|
||||
callout_init(&sc->ktls_tick, 1);
|
||||
|
||||
#ifdef TCP_OFFLOAD
|
||||
TASK_INIT(&sc->async_event_task, 0, t4_async_event, sc);
|
||||
#endif
|
||||
|
||||
rc = t4_map_bars_0_and_4(sc);
|
||||
if (rc != 0)
|
||||
goto done; /* error message displayed already */
|
||||
@ -1567,6 +1572,10 @@ t4_detach_common(device_t dev)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TCP_OFFLOAD
|
||||
taskqueue_drain(taskqueue_thread, &sc->async_event_task);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < sc->intr_count; i++)
|
||||
t4_free_irq(sc, &sc->irq[i]);
|
||||
|
||||
@ -2788,6 +2797,9 @@ t4_fatal_err(struct adapter *sc, bool fw_error)
|
||||
sc->flags |= ADAP_ERR;
|
||||
ADAPTER_UNLOCK(sc);
|
||||
}
|
||||
#ifdef TCP_OFFLOAD
|
||||
taskqueue_enqueue(taskqueue_thread, &sc->async_event_task);
|
||||
#endif
|
||||
|
||||
if (t4_panic_on_fatal_err) {
|
||||
log(LOG_ALERT, "%s: panic on fatal error after 30s",
|
||||
@ -10859,6 +10871,25 @@ t4_deactivate_uld(struct adapter *sc, int id)
|
||||
return (rc);
|
||||
}
|
||||
|
||||
static void
|
||||
t4_async_event(void *arg, int n)
|
||||
{
|
||||
struct uld_info *ui;
|
||||
struct adapter *sc = (struct adapter *)arg;
|
||||
|
||||
if (begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK, "t4async") != 0)
|
||||
return;
|
||||
sx_slock(&t4_uld_list_lock);
|
||||
SLIST_FOREACH(ui, &t4_uld_list, link) {
|
||||
if (ui->uld_id == ULD_IWARP) {
|
||||
ui->async_event(sc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
sx_sunlock(&t4_uld_list_lock);
|
||||
end_synchronized_op(sc, 0);
|
||||
}
|
||||
|
||||
int
|
||||
uld_active(struct adapter *sc, int uld_id)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user