RDMA/cxgb4: Connect_request_upcall fixes
When processing an MPA Start Request, if the listening endpoint is DEAD, then abort the connection. If the IWCM returns an error, then we must abort the connection and release resources. Also abort_connection() should not post a CLOSE event, so clean that up too. Signed-off-by: Steve Wise <swise@opengridcomputing.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
This commit is contained in:
Родитель
70b9c66053
Коммит
be13b2dff8
|
@ -968,13 +968,14 @@ static int act_establish(struct c4iw_dev *dev, struct sk_buff *skb)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void close_complete_upcall(struct c4iw_ep *ep)
|
static void close_complete_upcall(struct c4iw_ep *ep, int status)
|
||||||
{
|
{
|
||||||
struct iw_cm_event event;
|
struct iw_cm_event event;
|
||||||
|
|
||||||
PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
|
PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
|
||||||
memset(&event, 0, sizeof(event));
|
memset(&event, 0, sizeof(event));
|
||||||
event.event = IW_CM_EVENT_CLOSE;
|
event.event = IW_CM_EVENT_CLOSE;
|
||||||
|
event.status = status;
|
||||||
if (ep->com.cm_id) {
|
if (ep->com.cm_id) {
|
||||||
PDBG("close complete delivered ep %p cm_id %p tid %u\n",
|
PDBG("close complete delivered ep %p cm_id %p tid %u\n",
|
||||||
ep, ep->com.cm_id, ep->hwtid);
|
ep, ep->com.cm_id, ep->hwtid);
|
||||||
|
@ -988,7 +989,6 @@ static void close_complete_upcall(struct c4iw_ep *ep)
|
||||||
static int abort_connection(struct c4iw_ep *ep, struct sk_buff *skb, gfp_t gfp)
|
static int abort_connection(struct c4iw_ep *ep, struct sk_buff *skb, gfp_t gfp)
|
||||||
{
|
{
|
||||||
PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
|
PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
|
||||||
close_complete_upcall(ep);
|
|
||||||
state_set(&ep->com, ABORTING);
|
state_set(&ep->com, ABORTING);
|
||||||
set_bit(ABORT_CONN, &ep->com.history);
|
set_bit(ABORT_CONN, &ep->com.history);
|
||||||
return send_abort(ep, skb, gfp);
|
return send_abort(ep, skb, gfp);
|
||||||
|
@ -1067,9 +1067,10 @@ static void connect_reply_upcall(struct c4iw_ep *ep, int status)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void connect_request_upcall(struct c4iw_ep *ep)
|
static int connect_request_upcall(struct c4iw_ep *ep)
|
||||||
{
|
{
|
||||||
struct iw_cm_event event;
|
struct iw_cm_event event;
|
||||||
|
int ret;
|
||||||
|
|
||||||
PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
|
PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
|
||||||
memset(&event, 0, sizeof(event));
|
memset(&event, 0, sizeof(event));
|
||||||
|
@ -1094,15 +1095,14 @@ static void connect_request_upcall(struct c4iw_ep *ep)
|
||||||
event.private_data_len = ep->plen;
|
event.private_data_len = ep->plen;
|
||||||
event.private_data = ep->mpa_pkt + sizeof(struct mpa_message);
|
event.private_data = ep->mpa_pkt + sizeof(struct mpa_message);
|
||||||
}
|
}
|
||||||
if (state_read(&ep->parent_ep->com) != DEAD) {
|
c4iw_get_ep(&ep->com);
|
||||||
c4iw_get_ep(&ep->com);
|
ret = ep->parent_ep->com.cm_id->event_handler(ep->parent_ep->com.cm_id,
|
||||||
ep->parent_ep->com.cm_id->event_handler(
|
&event);
|
||||||
ep->parent_ep->com.cm_id,
|
if (ret)
|
||||||
&event);
|
c4iw_put_ep(&ep->com);
|
||||||
}
|
|
||||||
set_bit(CONNREQ_UPCALL, &ep->com.history);
|
set_bit(CONNREQ_UPCALL, &ep->com.history);
|
||||||
c4iw_put_ep(&ep->parent_ep->com);
|
c4iw_put_ep(&ep->parent_ep->com);
|
||||||
ep->parent_ep = NULL;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void established_upcall(struct c4iw_ep *ep)
|
static void established_upcall(struct c4iw_ep *ep)
|
||||||
|
@ -1401,7 +1401,6 @@ static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
PDBG("%s enter (%s line %u)\n", __func__, __FILE__, __LINE__);
|
PDBG("%s enter (%s line %u)\n", __func__, __FILE__, __LINE__);
|
||||||
stop_ep_timer(ep);
|
|
||||||
mpa = (struct mpa_message *) ep->mpa_pkt;
|
mpa = (struct mpa_message *) ep->mpa_pkt;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1494,9 +1493,17 @@ static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb)
|
||||||
ep->mpa_attr.p2p_type);
|
ep->mpa_attr.p2p_type);
|
||||||
|
|
||||||
state_set(&ep->com, MPA_REQ_RCVD);
|
state_set(&ep->com, MPA_REQ_RCVD);
|
||||||
|
stop_ep_timer(ep);
|
||||||
|
|
||||||
/* drive upcall */
|
/* drive upcall */
|
||||||
connect_request_upcall(ep);
|
mutex_lock(&ep->parent_ep->com.mutex);
|
||||||
|
if (ep->parent_ep->com.state != DEAD) {
|
||||||
|
if (connect_request_upcall(ep))
|
||||||
|
abort_connection(ep, skb, GFP_KERNEL);
|
||||||
|
} else {
|
||||||
|
abort_connection(ep, skb, GFP_KERNEL);
|
||||||
|
}
|
||||||
|
mutex_unlock(&ep->parent_ep->com.mutex);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2247,7 +2254,7 @@ static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb)
|
||||||
c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
|
c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
|
||||||
C4IW_QP_ATTR_NEXT_STATE, &attrs, 1);
|
C4IW_QP_ATTR_NEXT_STATE, &attrs, 1);
|
||||||
}
|
}
|
||||||
close_complete_upcall(ep);
|
close_complete_upcall(ep, 0);
|
||||||
__state_set(&ep->com, DEAD);
|
__state_set(&ep->com, DEAD);
|
||||||
release = 1;
|
release = 1;
|
||||||
disconnect = 0;
|
disconnect = 0;
|
||||||
|
@ -2426,7 +2433,7 @@ static int close_con_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
|
||||||
C4IW_QP_ATTR_NEXT_STATE,
|
C4IW_QP_ATTR_NEXT_STATE,
|
||||||
&attrs, 1);
|
&attrs, 1);
|
||||||
}
|
}
|
||||||
close_complete_upcall(ep);
|
close_complete_upcall(ep, 0);
|
||||||
__state_set(&ep->com, DEAD);
|
__state_set(&ep->com, DEAD);
|
||||||
release = 1;
|
release = 1;
|
||||||
break;
|
break;
|
||||||
|
@ -2981,7 +2988,7 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp)
|
||||||
rdev = &ep->com.dev->rdev;
|
rdev = &ep->com.dev->rdev;
|
||||||
if (c4iw_fatal_error(rdev)) {
|
if (c4iw_fatal_error(rdev)) {
|
||||||
fatal = 1;
|
fatal = 1;
|
||||||
close_complete_upcall(ep);
|
close_complete_upcall(ep, -EIO);
|
||||||
ep->com.state = DEAD;
|
ep->com.state = DEAD;
|
||||||
}
|
}
|
||||||
switch (ep->com.state) {
|
switch (ep->com.state) {
|
||||||
|
@ -3023,7 +3030,7 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp)
|
||||||
if (close) {
|
if (close) {
|
||||||
if (abrupt) {
|
if (abrupt) {
|
||||||
set_bit(EP_DISC_ABORT, &ep->com.history);
|
set_bit(EP_DISC_ABORT, &ep->com.history);
|
||||||
close_complete_upcall(ep);
|
close_complete_upcall(ep, -ECONNRESET);
|
||||||
ret = send_abort(ep, NULL, gfp);
|
ret = send_abort(ep, NULL, gfp);
|
||||||
} else {
|
} else {
|
||||||
set_bit(EP_DISC_CLOSE, &ep->com.history);
|
set_bit(EP_DISC_CLOSE, &ep->com.history);
|
||||||
|
@ -3435,6 +3442,7 @@ static void process_timeout(struct c4iw_ep *ep)
|
||||||
&attrs, 1);
|
&attrs, 1);
|
||||||
}
|
}
|
||||||
__state_set(&ep->com, ABORTING);
|
__state_set(&ep->com, ABORTING);
|
||||||
|
close_complete_upcall(ep, -ETIMEDOUT);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
WARN(1, "%s unexpected state ep %p tid %u state %u\n",
|
WARN(1, "%s unexpected state ep %p tid %u state %u\n",
|
||||||
|
|
Загрузка…
Ссылка в новой задаче