summaryrefslogtreecommitdiffstats
path: root/sys/dev/cxgbe/iw_cxgbe/cm.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/cxgbe/iw_cxgbe/cm.c')
-rw-r--r--sys/dev/cxgbe/iw_cxgbe/cm.c271
1 files changed, 179 insertions, 92 deletions
diff --git a/sys/dev/cxgbe/iw_cxgbe/cm.c b/sys/dev/cxgbe/iw_cxgbe/cm.c
index c884f5a..c2b72fa 100644
--- a/sys/dev/cxgbe/iw_cxgbe/cm.c
+++ b/sys/dev/cxgbe/iw_cxgbe/cm.c
@@ -80,7 +80,7 @@ static spinlock_t timeout_lock;
static void process_req(struct work_struct *ctx);
static void start_ep_timer(struct c4iw_ep *ep);
-static void stop_ep_timer(struct c4iw_ep *ep);
+static int stop_ep_timer(struct c4iw_ep *ep);
static int set_tcpinfo(struct c4iw_ep *ep);
static enum c4iw_ep_state state_read(struct c4iw_ep_common *epc);
static void __state_set(struct c4iw_ep_common *epc, enum c4iw_ep_state tostate);
@@ -96,14 +96,14 @@ static void send_mpa_req(struct c4iw_ep *ep);
static int send_mpa_reject(struct c4iw_ep *ep, const void *pdata, u8 plen);
static int send_mpa_reply(struct c4iw_ep *ep, const void *pdata, u8 plen);
static void close_complete_upcall(struct c4iw_ep *ep, int status);
-static int abort_connection(struct c4iw_ep *ep);
+static int send_abort(struct c4iw_ep *ep);
static void peer_close_upcall(struct c4iw_ep *ep);
static void peer_abort_upcall(struct c4iw_ep *ep);
static void connect_reply_upcall(struct c4iw_ep *ep, int status);
static int connect_request_upcall(struct c4iw_ep *ep);
static void established_upcall(struct c4iw_ep *ep);
-static void process_mpa_reply(struct c4iw_ep *ep);
-static void process_mpa_request(struct c4iw_ep *ep);
+static int process_mpa_reply(struct c4iw_ep *ep);
+static int process_mpa_request(struct c4iw_ep *ep);
static void process_peer_close(struct c4iw_ep *ep);
static void process_conn_error(struct c4iw_ep *ep);
static void process_close_complete(struct c4iw_ep *ep);
@@ -123,11 +123,11 @@ static void release_ep_resources(struct c4iw_ep *ep);
} while (0)
#define STOP_EP_TIMER(ep) \
- do { \
+ ({ \
CTR3(KTR_IW_CXGBE, "stop_ep_timer (%s:%d) ep %p", \
__func__, __LINE__, (ep)); \
stop_ep_timer(ep); \
- } while (0)
+ })
#ifdef KTR
static char *states[] = {
@@ -147,6 +147,34 @@ static char *states[] = {
};
#endif
+
+static void deref_cm_id(struct c4iw_ep_common *epc)
+{
+ epc->cm_id->rem_ref(epc->cm_id);
+ epc->cm_id = NULL;
+ set_bit(CM_ID_DEREFED, &epc->history);
+}
+
+static void ref_cm_id(struct c4iw_ep_common *epc)
+{
+ set_bit(CM_ID_REFED, &epc->history);
+ epc->cm_id->add_ref(epc->cm_id);
+}
+
+static void deref_qp(struct c4iw_ep *ep)
+{
+ c4iw_qp_rem_ref(&ep->com.qp->ibqp);
+ clear_bit(QP_REFERENCED, &ep->com.flags);
+ set_bit(QP_DEREFED, &ep->com.history);
+}
+
+static void ref_qp(struct c4iw_ep *ep)
+{
+ set_bit(QP_REFERENCED, &ep->com.flags);
+ set_bit(QP_REFED, &ep->com.history);
+ c4iw_qp_add_ref(&ep->com.qp->ibqp);
+}
+
static void
process_req(struct work_struct *ctx)
{
@@ -304,9 +332,7 @@ process_peer_close(struct c4iw_ep *ep)
disconnect = 0;
STOP_EP_TIMER(ep);
close_socket(&ep->com, 0);
- ep->com.cm_id->rem_ref(ep->com.cm_id);
- ep->com.cm_id = NULL;
- ep->com.qp = NULL;
+ deref_cm_id(&ep->com);
release = 1;
break;
@@ -490,6 +516,7 @@ process_close_complete(struct c4iw_ep *ep)
/* The cm_id may be null if we failed to connect */
mutex_lock(&ep->com.mutex);
+ set_bit(CLOSE_CON_RPL, &ep->com.history);
switch (ep->com.state) {
@@ -580,13 +607,14 @@ static void
process_data(struct c4iw_ep *ep)
{
struct sockaddr_in *local, *remote;
+ int disconnect = 0;
CTR5(KTR_IW_CXGBE, "%s: so %p, ep %p, state %s, sbused %d", __func__,
ep->com.so, ep, states[ep->com.state], sbused(&ep->com.so->so_rcv));
switch (state_read(&ep->com)) {
case MPA_REQ_SENT:
- process_mpa_reply(ep);
+ disconnect = process_mpa_reply(ep);
break;
case MPA_REQ_WAIT:
in_getsockaddr(ep->com.so, (struct sockaddr **)&local);
@@ -595,7 +623,7 @@ process_data(struct c4iw_ep *ep)
ep->com.remote_addr = *remote;
free(local, M_SONAME);
free(remote, M_SONAME);
- process_mpa_request(ep);
+ disconnect = process_mpa_request(ep);
break;
default:
if (sbused(&ep->com.so->so_rcv))
@@ -605,6 +633,9 @@ process_data(struct c4iw_ep *ep)
ep->com.so->so_state, sbused(&ep->com.so->so_rcv));
break;
}
+ if (disconnect)
+ c4iw_ep_disconnect(ep, disconnect == 2, GFP_KERNEL);
+
}
static void
@@ -749,9 +780,9 @@ int db_delay_usecs = 1;
SYSCTL_INT(_hw_iw_cxgbe, OID_AUTO, db_delay_usecs, CTLFLAG_RWTUN, &db_delay_usecs, 0,
"Usecs to delay awaiting db fifo to drain");
-static int dack_mode = 1;
+static int dack_mode = 0;
SYSCTL_INT(_hw_iw_cxgbe, OID_AUTO, dack_mode, CTLFLAG_RWTUN, &dack_mode, 0,
- "Delayed ack mode (default = 1)");
+ "Delayed ack mode (default = 0)");
int c4iw_max_read_depth = 8;
SYSCTL_INT(_hw_iw_cxgbe, OID_AUTO, c4iw_max_read_depth, CTLFLAG_RWTUN, &c4iw_max_read_depth, 0,
@@ -773,9 +804,9 @@ int c4iw_debug = 1;
SYSCTL_INT(_hw_iw_cxgbe, OID_AUTO, c4iw_debug, CTLFLAG_RWTUN, &c4iw_debug, 0,
"Enable debug logging (default = 0)");
-static int peer2peer;
+static int peer2peer = 1;
SYSCTL_INT(_hw_iw_cxgbe, OID_AUTO, peer2peer, CTLFLAG_RWTUN, &peer2peer, 0,
- "Support peer2peer ULPs (default = 0)");
+ "Support peer2peer ULPs (default = 1)");
static int p2p_type = FW_RI_INIT_P2PTYPE_READ_REQ;
SYSCTL_INT(_hw_iw_cxgbe, OID_AUTO, p2p_type, CTLFLAG_RWTUN, &p2p_type, 0,
@@ -827,14 +858,16 @@ start_ep_timer(struct c4iw_ep *ep)
add_timer(&ep->timer);
}
-static void
+static int
stop_ep_timer(struct c4iw_ep *ep)
{
del_timer_sync(&ep->timer);
if (!test_and_set_bit(TIMEOUT, &ep->com.flags)) {
c4iw_put_ep(&ep->com);
+ return 0;
}
+ return 1;
}
static enum
@@ -900,6 +933,8 @@ void _c4iw_free_ep(struct kref *kref)
epc = &ep->com;
KASSERT(!epc->entry.tqe_prev, ("%s epc %p still on req list",
__func__, epc));
+ if (test_bit(QP_REFERENCED, &ep->com.flags))
+ deref_qp(ep);
kfree(ep);
}
@@ -1175,20 +1210,17 @@ static void close_complete_upcall(struct c4iw_ep *ep, int status)
CTR2(KTR_IW_CXGBE, "%s:ccu1 %1", __func__, ep);
ep->com.cm_id->event_handler(ep->com.cm_id, &event);
- ep->com.cm_id->rem_ref(ep->com.cm_id);
- ep->com.cm_id = NULL;
- ep->com.qp = NULL;
+ deref_cm_id(&ep->com);
set_bit(CLOSE_UPCALL, &ep->com.history);
}
CTR2(KTR_IW_CXGBE, "%s:ccuE %p", __func__, ep);
}
-static int abort_connection(struct c4iw_ep *ep)
+static int send_abort(struct c4iw_ep *ep)
{
int err;
CTR2(KTR_IW_CXGBE, "%s:abB %p", __func__, ep);
- state_set(&ep->com, ABORTING);
abort_socket(ep);
err = close_socket(&ep->com, 0);
set_bit(ABORT_CONN, &ep->com.history);
@@ -1226,9 +1258,7 @@ static void peer_abort_upcall(struct c4iw_ep *ep)
CTR2(KTR_IW_CXGBE, "%s:pau1 %p", __func__, ep);
ep->com.cm_id->event_handler(ep->com.cm_id, &event);
- ep->com.cm_id->rem_ref(ep->com.cm_id);
- ep->com.cm_id = NULL;
- ep->com.qp = NULL;
+ deref_cm_id(&ep->com);
set_bit(ABORT_UPCALL, &ep->com.history);
}
CTR2(KTR_IW_CXGBE, "%s:pauE %p", __func__, ep);
@@ -1282,9 +1312,7 @@ static void connect_reply_upcall(struct c4iw_ep *ep, int status)
if (status < 0) {
CTR3(KTR_IW_CXGBE, "%s:cru4 %p %d", __func__, ep, status);
- ep->com.cm_id->rem_ref(ep->com.cm_id);
- ep->com.cm_id = NULL;
- ep->com.qp = NULL;
+ deref_cm_id(&ep->com);
}
CTR2(KTR_IW_CXGBE, "%s:cruE %p", __func__, ep);
@@ -1353,8 +1381,19 @@ static void established_upcall(struct c4iw_ep *ep)
}
-
-static void process_mpa_reply(struct c4iw_ep *ep)
+/*
+ * process_mpa_reply - process streaming mode MPA reply
+ *
+ * Returns:
+ *
+ * 0 upon success indicating a connect request was delivered to the ULP
+ * or the mpa request is incomplete but valid so far.
+ *
+ * 1 if a failure requires the caller to close the connection.
+ *
+ * 2 if a failure requires the caller to abort the connection.
+ */
+static int process_mpa_reply(struct c4iw_ep *ep)
{
struct mpa_message *mpa;
struct mpa_v2_conn_params *mpa_v2_params;
@@ -1367,17 +1406,17 @@ static void process_mpa_reply(struct c4iw_ep *ep)
struct mbuf *top, *m;
int flags = MSG_DONTWAIT;
struct uio uio;
+ int disconnect = 0;
CTR2(KTR_IW_CXGBE, "%s:pmrB %p", __func__, ep);
/*
- * Stop mpa timer. If it expired, then the state has
- * changed and we bail since ep_timeout already aborted
- * the connection.
+ * Stop mpa timer. If it expired, then
+ * we ignore the MPA reply. process_timeout()
+ * will abort the connection.
*/
- STOP_EP_TIMER(ep);
- if (state_read(&ep->com) != MPA_REQ_SENT)
- return;
+ if (STOP_EP_TIMER(ep))
+ return 0;
uio.uio_resid = 1000000;
uio.uio_td = ep->com.thread;
@@ -1389,7 +1428,7 @@ static void process_mpa_reply(struct c4iw_ep *ep)
CTR2(KTR_IW_CXGBE, "%s:pmr1 %p", __func__, ep);
START_EP_TIMER(ep);
- return;
+ return 0;
}
err = -err;
CTR2(KTR_IW_CXGBE, "%s:pmr2 %p", __func__, ep);
@@ -1417,7 +1456,7 @@ static void process_mpa_reply(struct c4iw_ep *ep)
CTR3(KTR_IW_CXGBE, "%s:pmr5 %p %d", __func__, ep,
ep->mpa_pkt_len + m->m_len);
err = (-EINVAL);
- goto err;
+ goto err_stop_timer;
}
/*
@@ -1435,8 +1474,9 @@ static void process_mpa_reply(struct c4iw_ep *ep)
/*
* if we don't even have the mpa message, then bail.
*/
- if (ep->mpa_pkt_len < sizeof(*mpa))
- return;
+ if (ep->mpa_pkt_len < sizeof(*mpa)) {
+ return 0;
+ }
mpa = (struct mpa_message *) ep->mpa_pkt;
/* Validate MPA header. */
@@ -1447,14 +1487,14 @@ static void process_mpa_reply(struct c4iw_ep *ep)
printk(KERN_ERR MOD "%s MPA version mismatch. Local = %d, "
" Received = %d\n", __func__, mpa_rev, mpa->revision);
err = -EPROTO;
- goto err;
+ goto err_stop_timer;
}
if (memcmp(mpa->key, MPA_KEY_REP, sizeof(mpa->key))) {
CTR2(KTR_IW_CXGBE, "%s:pmr7 %p", __func__, ep);
err = -EPROTO;
- goto err;
+ goto err_stop_timer;
}
plen = ntohs(mpa->private_data_size);
@@ -1466,7 +1506,7 @@ static void process_mpa_reply(struct c4iw_ep *ep)
CTR2(KTR_IW_CXGBE, "%s:pmr8 %p", __func__, ep);
err = -EPROTO;
- goto err;
+ goto err_stop_timer;
}
/*
@@ -1475,8 +1515,9 @@ static void process_mpa_reply(struct c4iw_ep *ep)
if (ep->mpa_pkt_len > (sizeof(*mpa) + plen)) {
CTR2(KTR_IW_CXGBE, "%s:pmr9 %p", __func__, ep);
+ STOP_EP_TIMER(ep);
err = -EPROTO;
- goto err;
+ goto err_stop_timer;
}
ep->plen = (u8) plen;
@@ -1488,14 +1529,14 @@ static void process_mpa_reply(struct c4iw_ep *ep)
if (ep->mpa_pkt_len < (sizeof(*mpa) + plen)) {
CTR2(KTR_IW_CXGBE, "%s:pmra %p", __func__, ep);
- return;
+ return 0;
}
if (mpa->flags & MPA_REJECT) {
CTR2(KTR_IW_CXGBE, "%s:pmrb %p", __func__, ep);
err = -ECONNREFUSED;
- goto err;
+ goto err_stop_timer;
}
/*
@@ -1638,6 +1679,7 @@ static void process_mpa_reply(struct c4iw_ep *ep)
err = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
C4IW_QP_ATTR_NEXT_STATE, &attrs, 0);
err = -ENOMEM;
+ disconnect = 1;
goto out;
}
@@ -1658,19 +1700,33 @@ static void process_mpa_reply(struct c4iw_ep *ep)
err = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
C4IW_QP_ATTR_NEXT_STATE, &attrs, 0);
err = -ENOMEM;
+ disconnect = 1;
goto out;
}
goto out;
+err_stop_timer:
+ STOP_EP_TIMER(ep);
err:
- state_set(&ep->com, ABORTING);
- abort_connection(ep);
+ disconnect = 2;
out:
connect_reply_upcall(ep, err);
CTR2(KTR_IW_CXGBE, "%s:pmrE %p", __func__, ep);
- return;
+ return disconnect;
}
-static void
+/*
+ * process_mpa_request - process streaming mode MPA request
+ *
+ * Returns:
+ *
+ * 0 upon success indicating a connect request was delivered to the ULP
+ * or the mpa request is incomplete but valid so far.
+ *
+ * 1 if a failure requires the caller to close the connection.
+ *
+ * 2 if a failure requires the caller to abort the connection.
+ */
+static int
process_mpa_request(struct c4iw_ep *ep)
{
struct mpa_message *mpa;
@@ -1684,7 +1740,7 @@ process_mpa_request(struct c4iw_ep *ep)
CTR3(KTR_IW_CXGBE, "%s: ep %p, state %s", __func__, ep, states[state]);
if (state != MPA_REQ_WAIT)
- return;
+ return 0;
iov.iov_base = &ep->mpa_pkt[ep->mpa_pkt_len];
iov.iov_len = sizeof(ep->mpa_pkt) - ep->mpa_pkt_len;
@@ -1698,13 +1754,10 @@ process_mpa_request(struct c4iw_ep *ep)
rc = soreceive(ep->com.so, NULL, &uio, NULL, NULL, &flags);
if (rc == EAGAIN)
- return;
- else if (rc) {
-abort:
- STOP_EP_TIMER(ep);
- abort_connection(ep);
- return;
- }
+ return 0;
+ else if (rc)
+ goto err_stop_timer;
+
KASSERT(uio.uio_offset > 0, ("%s: sorecieve on so %p read no data",
__func__, ep->com.so));
ep->mpa_pkt_len += uio.uio_offset;
@@ -1718,7 +1771,7 @@ abort:
/* Don't even have the MPA message. Wait for more data to arrive. */
if (ep->mpa_pkt_len < sizeof(*mpa))
- return;
+ return 0;
mpa = (struct mpa_message *) ep->mpa_pkt;
/*
@@ -1727,24 +1780,24 @@ abort:
if (mpa->revision > mpa_rev) {
log(LOG_ERR, "%s: MPA version mismatch. Local = %d,"
" Received = %d\n", __func__, mpa_rev, mpa->revision);
- goto abort;
+ goto err_stop_timer;
}
if (memcmp(mpa->key, MPA_KEY_REQ, sizeof(mpa->key)))
- goto abort;
+ goto err_stop_timer;
/*
* Fail if there's too much private data.
*/
plen = ntohs(mpa->private_data_size);
if (plen > MPA_MAX_PRIVATE_DATA)
- goto abort;
+ goto err_stop_timer;
/*
* If plen does not account for pkt size
*/
if (ep->mpa_pkt_len > (sizeof(*mpa) + plen))
- goto abort;
+ goto err_stop_timer;
ep->plen = (u8) plen;
@@ -1752,7 +1805,7 @@ abort:
* If we don't have all the pdata yet, then bail.
*/
if (ep->mpa_pkt_len < (sizeof(*mpa) + plen))
- return;
+ return 0;
/*
* If we get here we have accumulated the entire mpa
@@ -1794,7 +1847,7 @@ abort:
ep->mpa_attr.p2p_type = p2p_type;
if (set_tcpinfo(ep))
- goto abort;
+ goto err_stop_timer;
CTR5(KTR_IW_CXGBE, "%s: crc_enabled = %d, recv_marker_enabled = %d, "
"xmit_marker_enabled = %d, version = %d", __func__,
@@ -1807,12 +1860,18 @@ abort:
/* drive upcall */
mutex_lock(&ep->parent_ep->com.mutex);
if (ep->parent_ep->com.state != DEAD) {
- if(connect_request_upcall(ep)) {
- abort_connection(ep);
- }
- }else
- abort_connection(ep);
+ if(connect_request_upcall(ep))
+ goto err_out;
+ }else {
+ goto err_out;
+ }
mutex_unlock(&ep->parent_ep->com.mutex);
+ return 0;
+
+err_stop_timer:
+ STOP_EP_TIMER(ep);
+err_out:
+ return 2;
}
/*
@@ -1825,6 +1884,7 @@ int c4iw_reject_cr(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len)
int err;
struct c4iw_ep *ep = to_ep(cm_id);
CTR2(KTR_IW_CXGBE, "%s:crcB %p", __func__, ep);
+ int disconnect = 0;
if (state_read(&ep->com) == DEAD) {
@@ -1838,7 +1898,7 @@ int c4iw_reject_cr(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len)
if (mpa_rev == 0) {
CTR2(KTR_IW_CXGBE, "%s:crc2 %p", __func__, ep);
- abort_connection(ep);
+ disconnect = 2;
}
else {
@@ -1847,6 +1907,8 @@ int c4iw_reject_cr(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len)
err = soshutdown(ep->com.so, 3);
}
c4iw_put_ep(&ep->com);
+ if (disconnect)
+ err = c4iw_ep_disconnect(ep, disconnect == 2, GFP_KERNEL);
CTR2(KTR_IW_CXGBE, "%s:crc4 %p", __func__, ep);
return 0;
}
@@ -1859,6 +1921,7 @@ int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
struct c4iw_ep *ep = to_ep(cm_id);
struct c4iw_dev *h = to_c4iw_dev(cm_id->device);
struct c4iw_qp *qp = get_qhp(h, conn_param->qpn);
+ int abort = 0;
CTR2(KTR_IW_CXGBE, "%s:cacB %p", __func__, ep);
@@ -1866,7 +1929,7 @@ int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
CTR2(KTR_IW_CXGBE, "%s:cac1 %p", __func__, ep);
err = -ECONNRESET;
- goto err;
+ goto err_out;
}
BUG_ON(state_read(&ep->com) != MPA_REQ_RCVD);
@@ -1878,9 +1941,8 @@ int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
(conn_param->ird > c4iw_max_read_depth)) {
CTR2(KTR_IW_CXGBE, "%s:cac2 %p", __func__, ep);
- abort_connection(ep);
err = -EINVAL;
- goto err;
+ goto err_abort;
}
if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) {
@@ -1894,9 +1956,8 @@ int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
ep->ord = conn_param->ord;
send_mpa_reject(ep, conn_param->private_data,
conn_param->private_data_len);
- abort_connection(ep);
err = -ENOMEM;
- goto err;
+ goto err_abort;
}
if (conn_param->ird > ep->ord) {
@@ -1910,9 +1971,8 @@ int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
}
else {
CTR2(KTR_IW_CXGBE, "%s:cac7 %p", __func__, ep);
- abort_connection(ep);
err = -ENOMEM;
- goto err;
+ goto err_abort;
}
}
@@ -1932,9 +1992,10 @@ int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
}
- cm_id->add_ref(cm_id);
ep->com.cm_id = cm_id;
+ ref_cm_id(&ep->com);
ep->com.qp = qp;
+ ref_qp(ep);
//ep->ofld_txq = TOEPCB(ep->com.so)->ofld_txq;
/* bind QP to EP and move to RTS */
@@ -1956,7 +2017,7 @@ int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
if (err) {
CTR2(KTR_IW_CXGBE, "%s:caca %p", __func__, ep);
- goto err1;
+ goto err_defef_cm_id;
}
err = send_mpa_reply(ep, conn_param->private_data,
conn_param->private_data_len);
@@ -1964,7 +2025,7 @@ int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
if (err) {
CTR2(KTR_IW_CXGBE, "%s:caca %p", __func__, ep);
- goto err1;
+ goto err_defef_cm_id;
}
state_set(&ep->com, FPDU_MODE);
@@ -1972,11 +2033,13 @@ int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
c4iw_put_ep(&ep->com);
CTR2(KTR_IW_CXGBE, "%s:cacE %p", __func__, ep);
return 0;
-err1:
- ep->com.cm_id = NULL;
- ep->com.qp = NULL;
- cm_id->rem_ref(cm_id);
-err:
+err_defef_cm_id:
+ deref_cm_id(&ep->com);
+err_abort:
+ abort = 1;
+err_out:
+ if (abort)
+ c4iw_ep_disconnect(ep, 1, GFP_KERNEL);
c4iw_put_ep(&ep->com);
CTR2(KTR_IW_CXGBE, "%s:cacE err %p", __func__, ep);
return err;
@@ -2028,9 +2091,9 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
ep->ord = 1;
}
- cm_id->add_ref(cm_id);
ep->com.dev = dev;
ep->com.cm_id = cm_id;
+ ref_cm_id(&ep->com);
ep->com.qp = get_qhp(dev, conn_param->qpn);
if (!ep->com.qp) {
@@ -2039,6 +2102,7 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
err = -EINVAL;
goto fail2;
}
+ ref_qp(ep);
ep->com.thread = curthread;
ep->com.so = cm_id->so;
@@ -2096,7 +2160,7 @@ fail3:
CTR2(KTR_IW_CXGBE, "%s:ccb %p", __func__, ep);
fib4_free_nh_ext(RT_DEFAULT_FIB, &nh4);
fail2:
- cm_id->rem_ref(cm_id);
+ deref_cm_id(&ep->com);
c4iw_put_ep(&ep->com);
out:
CTR2(KTR_IW_CXGBE, "%s:ccE %p", __func__, ep);
@@ -2124,8 +2188,8 @@ c4iw_create_listen_ep(struct iw_cm_id *cm_id, int backlog)
goto failed;
}
- cm_id->add_ref(cm_id);
ep->com.cm_id = cm_id;
+ ref_cm_id(&ep->com);
ep->com.dev = dev;
ep->backlog = backlog;
ep->com.local_addr = cm_id->local_addr;
@@ -2150,7 +2214,7 @@ c4iw_destroy_listen_ep(struct iw_cm_id *cm_id)
cm_id->so, states[ep->com.state]);
state_set(&ep->com, DEAD);
- cm_id->rem_ref(cm_id);
+ deref_cm_id(&ep->com);
c4iw_put_ep(&ep->com);
return;
@@ -2232,7 +2296,8 @@ 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);
- ret = abort_connection(ep);
+ close_complete_upcall(ep, -ECONNRESET);
+ ret = send_abort(ep);
} else {
CTR2(KTR_IW_CXGBE, "%s:ced5 %p", __func__, ep);
@@ -2250,8 +2315,25 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp)
}
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;
+ 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__);
+ }
+ }
release_ep_resources(ep);
+ ep->com.state = DEAD;
CTR2(KTR_IW_CXGBE, "%s:ced6 %p", __func__, ep);
}
CTR2(KTR_IW_CXGBE, "%s:cedE %p", __func__, ep);
@@ -2290,8 +2372,13 @@ static void ep_timeout(unsigned long arg)
if (!test_and_set_bit(TIMEOUT, &ep->com.flags)) {
- list_add_tail(&ep->entry, &timeout_list);
- kickit = 1;
+ /*
+ * Only insert if it is not already on the list.
+ */
+ if (!ep->entry.next) {
+ list_add_tail(&ep->entry, &timeout_list);
+ kickit = 1;
+ }
}
spin_unlock(&timeout_lock);
OpenPOWER on IntegriCloud