[openib-general] [PATCH] [CM] add support to repeat MRA messages

Sean Hefty sean.hefty at intel.com
Mon May 23 14:55:12 PDT 2005


The following patch adds support to repeat MRA messages in response to
receiving a duplicate REQ, REP, or LAP.

Signed-off-by: Sean Hefty <sean.hefty at intel.com>



Index: cm.c
===================================================================
--- cm.c	(revision 2417)
+++ cm.c	(working copy)
@@ -143,6 +143,7 @@ struct cm_id_private {
 	u8 local_ack_timeout;
 	u8 retry_count;
 	u8 rnr_retry_count;
+	u8 service_timeout;
 
 	struct list_head work_list;
 	atomic_t work_count;
@@ -292,12 +293,10 @@ static void cm_free_id(u32 local_id)
 	spin_unlock_irqrestore(&cm.lock, flags);
 }
 
-static struct cm_id_private * cm_acquire_id(u32 local_id, u32 remote_id)
+static struct cm_id_private * cm_get_id(u32 local_id, u32 remote_id)
 {
 	struct cm_id_private *cm_id_priv;
-	unsigned long flags;
 
-	spin_lock_irqsave(&cm.lock, flags);
 	cm_id_priv = idr_find(&cm.local_id_table, (int) local_id);
 	if (cm_id_priv) {
 		if (cm_id_priv->id.remote_id == remote_id)
@@ -305,6 +304,17 @@ static struct cm_id_private * cm_acquire
 		else
 			cm_id_priv = NULL;
 	}
+
+	return cm_id_priv;
+}
+
+static struct cm_id_private * cm_acquire_id(u32 local_id, u32 remote_id)
+{
+	struct cm_id_private *cm_id_priv;
+	unsigned long flags;
+
+	spin_lock_irqsave(&cm.lock, flags);
+	cm_id_priv = cm_get_id(local_id, remote_id);
 	spin_unlock_irqrestore(&cm.lock, flags);
 
 	return cm_id_priv;
@@ -1029,18 +1039,175 @@ static void cm_process_work(struct cm_id
 		ib_destroy_cm_id(&cm_id_priv->id);	
 }
 
+static void cm_format_mra(struct cm_mra_msg *mra_msg,
+			  struct cm_id_private *cm_id_priv,
+			  enum cm_msg_response msg_mraed, u8 service_timeout,
+			  const void *private_data, u8 private_data_len)
+{
+	/* todo: TID should match REQ or LAP */
+	if (msg_mraed == CM_MSG_RESPONSE_OTHER)
+		cm_format_mad_hdr(&mra_msg->hdr, CM_MRA_ATTR_ID,
+				  cm_form_tid(cm_id_priv, CM_MSG_SEQUENCE_LAP));
+	else
+		cm_format_mad_hdr(&mra_msg->hdr, CM_MRA_ATTR_ID,
+				  cm_form_tid(cm_id_priv, CM_MSG_SEQUENCE_REQ));
+
+	cm_mra_set_msg_mraed(mra_msg, msg_mraed);
+
+	mra_msg->local_comm_id = cm_id_priv->id.local_id;
+	mra_msg->remote_comm_id = cm_id_priv->id.remote_id;
+	cm_mra_set_service_timeout(mra_msg, service_timeout);
+
+	if (private_data && private_data_len)
+		memcpy(mra_msg->private_data, private_data, private_data_len);
+}
+
+static void cm_format_rej(struct cm_rej_msg *rej_msg,
+			  struct cm_id_private *cm_id_priv,
+			  enum ib_cm_rej_reason reason,
+			  void *ari,
+			  u8 ari_length,
+			  const void *private_data,
+			  u8 private_data_len)
+{
+	/* todo: TID should match received REQ */
+	cm_format_mad_hdr(&rej_msg->hdr, CM_REJ_ATTR_ID,
+			  cm_form_tid(cm_id_priv, CM_MSG_SEQUENCE_REQ));
+
+	rej_msg->remote_comm_id = cm_id_priv->id.remote_id;
+
+	switch(cm_id_priv->id.state) {
+	case IB_CM_REQ_RCVD:
+		rej_msg->local_comm_id = 0;
+		cm_rej_set_msg_rejected(rej_msg, CM_MSG_RESPONSE_REQ);
+		break;
+	case IB_CM_MRA_REQ_SENT:
+		rej_msg->local_comm_id = cm_id_priv->id.local_id;
+		cm_rej_set_msg_rejected(rej_msg, CM_MSG_RESPONSE_REQ);
+		break;
+	case IB_CM_REP_RCVD:
+	case IB_CM_MRA_REP_SENT:
+		rej_msg->local_comm_id = cm_id_priv->id.local_id;
+		cm_rej_set_msg_rejected(rej_msg, CM_MSG_RESPONSE_REP);
+		break;
+	default:
+		rej_msg->local_comm_id = cm_id_priv->id.local_id;
+		cm_rej_set_msg_rejected(rej_msg, CM_MSG_RESPONSE_OTHER);
+		break;
+	}
+
+	rej_msg->reason = reason;
+	if (ari && ari_length) {
+		cm_rej_set_reject_info_len(rej_msg, ari_length);
+		memcpy(rej_msg->ari, ari, ari_length);
+	}
+
+	if (private_data && private_data_len)
+		memcpy(rej_msg->private_data, private_data, private_data_len);
+}
+
+static void cm_dup_req_handler(struct cm_work *work,
+			       struct cm_id_private *cm_id_priv)
+{
+	struct ib_mad_send_buf *msg = NULL;
+	struct ib_send_wr *bad_send_wr;
+	unsigned long flags;
+	int ret;
+
+	/* Quick state check to discard duplicate REQs. */
+	if (cm_id_priv->id.state == IB_CM_REQ_RCVD)
+		return;
+
+	ret = cm_alloc_response_msg(work->port, work->mad_recv_wc, &msg);
+	if (ret)
+		return;
+
+	spin_lock_irqsave(&cm_id_priv->lock, flags);
+	switch (cm_id_priv->id.state) {
+	case IB_CM_MRA_REQ_SENT:
+		cm_format_mra((struct cm_mra_msg *) msg->mad, cm_id_priv,
+			      CM_MSG_RESPONSE_REQ, cm_id_priv->service_timeout,
+			      cm_id_priv->private_data,
+			      cm_id_priv->private_data_len);
+		break;
+	case IB_CM_TIMEWAIT:
+		cm_format_rej((struct cm_rej_msg *) msg->mad, cm_id_priv,
+			      IB_CM_REJ_STALE_CONN, NULL, 0, NULL, 0);
+		break;
+	default:
+		goto unlock;
+	}
+	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+
+	ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent, &msg->send_wr,
+			       &bad_send_wr);
+	if (ret)
+		goto free;
+	return;
+
+unlock:	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+free:	cm_free_msg(msg);
+}
+
+static struct cm_id_private * cm_match_req(struct cm_work *work,
+					   struct cm_id_private *cm_id_priv)
+{
+	struct cm_id_private *listen_cm_id_priv, *cur_cm_id_priv;
+	struct cm_timewait_info *timewait_info;
+	struct cm_req_msg *req_msg;
+	unsigned long flags;
+
+	req_msg = (struct cm_req_msg *)work->mad_recv_wc->recv_buf.mad;
+
+	/* Check for duplicate REQ and stale connections. */
+	spin_lock_irqsave(&cm.lock, flags);
+	timewait_info = cm_insert_remote_id(cm_id_priv->timewait_info);
+	if (!timewait_info)
+		timewait_info = cm_insert_remote_qpn(cm_id_priv->timewait_info);
+
+	if (timewait_info) {
+		cur_cm_id_priv = cm_get_id(timewait_info->work.local_id,
+					   timewait_info->work.remote_id);
+		spin_unlock_irqrestore(&cm.lock, flags);
+		if (cur_cm_id_priv) {
+			cm_dup_req_handler(work, cur_cm_id_priv);
+			cm_deref_id(cur_cm_id_priv);
+		} else
+			cm_issue_rej(work->port, work->mad_recv_wc,
+				     IB_CM_REJ_STALE_CONN, CM_MSG_RESPONSE_REQ,
+				     NULL, 0);
+		goto error;
+	}
+
+	/* Find matching listen request. */
+	listen_cm_id_priv = cm_find_listen(req_msg->service_id);
+	if (!listen_cm_id_priv) {
+		spin_unlock_irqrestore(&cm.lock, flags);
+		cm_issue_rej(work->port, work->mad_recv_wc,
+			     IB_CM_REJ_INVALID_SERVICE_ID, CM_MSG_RESPONSE_REQ,
+			     NULL, 0);
+		goto error;
+	}
+	atomic_inc(&listen_cm_id_priv->refcount);
+	atomic_inc(&cm_id_priv->refcount);
+	cm_id_priv->id.state = IB_CM_REQ_RCVD;
+	atomic_inc(&cm_id_priv->work_count);
+	spin_unlock_irqrestore(&cm.lock, flags);
+	return listen_cm_id_priv;
+
+error:	cm_cleanup_timewait(cm_id_priv->timewait_info);
+	return NULL;
+}
+
 static int cm_req_handler(struct cm_work *work)
 {
 	struct ib_cm_id *cm_id;
 	struct cm_id_private *cm_id_priv, *listen_cm_id_priv;
 	struct cm_req_msg *req_msg;
-	unsigned long flags;
 	int ret;
 
 	req_msg = (struct cm_req_msg *)work->mad_recv_wc->recv_buf.mad;
 
-	/* todo: Check for peer-to-peer connection. */
-
 	cm_id = ib_create_cm_id(NULL, NULL);
 	if (IS_ERR(cm_id))
 		return PTR_ERR(cm_id);
@@ -1059,37 +1226,11 @@ static int cm_req_handler(struct cm_work
 	cm_id_priv->timewait_info->remote_ca_guid = req_msg->local_ca_guid;
 	cm_id_priv->timewait_info->remote_qpn = cm_req_get_local_qpn(req_msg);
 
-	spin_lock_irqsave(&cm.lock, flags);
-	/* Check for duplicate REQ. */
-	if (cm_insert_remote_id(cm_id_priv->timewait_info)) {
-		spin_unlock_irqrestore(&cm.lock, flags);
-		ret = -EINVAL;
-		goto error2;
-	}
-	/* Check for a stale connection. */
-	if (cm_insert_remote_qpn(cm_id_priv->timewait_info)) {
-		spin_unlock_irqrestore(&cm.lock, flags);
-		cm_issue_rej(work->port, work->mad_recv_wc,
-			     IB_CM_REJ_STALE_CONN, CM_MSG_RESPONSE_REQ,
-			     NULL, 0);
-		ret = -EINVAL;
-		goto error2;
-	}
-	/* Find matching listen request. */
-	listen_cm_id_priv = cm_find_listen(req_msg->service_id);
+	listen_cm_id_priv = cm_match_req(work, cm_id_priv);
 	if (!listen_cm_id_priv) {
-		spin_unlock_irqrestore(&cm.lock, flags);
-		cm_issue_rej(work->port, work->mad_recv_wc,
-			     IB_CM_REJ_INVALID_SERVICE_ID, CM_MSG_RESPONSE_REQ,
-			     NULL, 0);
 		ret = -EINVAL;
 		goto error2;
 	}
-	atomic_inc(&listen_cm_id_priv->refcount);
-	atomic_inc(&cm_id_priv->refcount);
-	cm_id_priv->id.state = IB_CM_REQ_RCVD;
-	atomic_inc(&cm_id_priv->work_count);
-	spin_unlock_irqrestore(&cm.lock, flags);
 
 	cm_id_priv->id.cm_handler = listen_cm_id_priv->id.cm_handler;
 	cm_id_priv->id.context = listen_cm_id_priv->id.context;
@@ -1125,8 +1266,8 @@ static int cm_req_handler(struct cm_work
 
 error3:	atomic_dec(&cm_id_priv->refcount);
 	cm_deref_id(listen_cm_id_priv);
-error2:	cm_cleanup_timewait(cm_id_priv->timewait_info);
-	kfree(cm_id_priv->timewait_info);
+	cm_cleanup_timewait(cm_id_priv->timewait_info);
+error2:	kfree(cm_id_priv->timewait_info);
 error1:	ib_destroy_cm_id(&cm_id_priv->id);
 	return ret;
 }
@@ -1291,7 +1432,7 @@ static void cm_dup_rep_handler(struct cm
 {
 	struct cm_id_private *cm_id_priv;
 	struct cm_rep_msg *rep_msg;
-	struct ib_mad_send_buf *msg;
+	struct ib_mad_send_buf *msg = NULL;
 	struct ib_send_wr *bad_send_wr;
 	unsigned long flags;
 	int ret;
@@ -1304,26 +1445,31 @@ static void cm_dup_rep_handler(struct cm
 
 	ret = cm_alloc_response_msg(work->port, work->mad_recv_wc, &msg);
 	if (ret)
-		goto out;
+		goto deref;
 
 	spin_lock_irqsave(&cm_id_priv->lock, flags);
-	if (cm_id_priv->id.state != IB_CM_ESTABLISHED ||
-	    cm_id_priv->id.lap_state != IB_CM_LAP_IDLE) {
-		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
-		goto error;
-	}
-	cm_format_rtu((struct cm_rtu_msg *) msg->mad, cm_id_priv,
-		      cm_id_priv->private_data, cm_id_priv->private_data_len);
+	if (cm_id_priv->id.state == IB_CM_ESTABLISHED)
+		cm_format_rtu((struct cm_rtu_msg *) msg->mad, cm_id_priv,
+			      cm_id_priv->private_data,
+			      cm_id_priv->private_data_len);
+	else if (cm_id_priv->id.state == IB_CM_MRA_REP_SENT)
+		cm_format_mra((struct cm_mra_msg *) msg->mad, cm_id_priv,
+			      CM_MSG_RESPONSE_REP, cm_id_priv->service_timeout,
+			      cm_id_priv->private_data,
+			      cm_id_priv->private_data_len);
+	else
+		goto unlock;
 	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
 
 	ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent, &msg->send_wr,
 			       &bad_send_wr);
 	if (ret)
-		goto error;
-	goto out;
+		goto free;
+	goto deref;
 
-error:	cm_free_msg(msg);
-out:	cm_deref_id(cm_id_priv);
+unlock:	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+free:	cm_free_msg(msg);
+deref:	cm_deref_id(cm_id_priv);
 }
 
 static int cm_rep_handler(struct cm_work *work)
@@ -1593,7 +1739,7 @@ static int cm_dreq_handler(struct cm_wor
 {
 	struct cm_id_private *cm_id_priv;
 	struct cm_dreq_msg *dreq_msg;
-	struct ib_mad_send_buf *msg;
+	struct ib_mad_send_buf *msg = NULL;
 	struct ib_send_wr *bad_send_wr;
 	unsigned long flags;
 	int ret;
@@ -1689,50 +1835,6 @@ out:
 	return -EINVAL;
 }
 
-static void cm_format_rej(struct cm_rej_msg *rej_msg,
-			  struct cm_id_private *cm_id_priv,
-			  enum ib_cm_rej_reason reason,
-			  void *ari,
-			  u8 ari_length,
-			  const void *private_data,
-			  u8 private_data_len)
-{
-	/* todo: TID should match received REQ */
-	cm_format_mad_hdr(&rej_msg->hdr, CM_REJ_ATTR_ID,
-			  cm_form_tid(cm_id_priv, CM_MSG_SEQUENCE_REQ));
-
-	rej_msg->remote_comm_id = cm_id_priv->id.remote_id;
-
-	switch(cm_id_priv->id.state) {
-	case IB_CM_REQ_RCVD:
-		rej_msg->local_comm_id = 0;
-		cm_rej_set_msg_rejected(rej_msg, CM_MSG_RESPONSE_REQ);
-		break;
-	case IB_CM_MRA_REQ_SENT:
-		rej_msg->local_comm_id = cm_id_priv->id.local_id;
-		cm_rej_set_msg_rejected(rej_msg, CM_MSG_RESPONSE_REQ);
-		break;
-	case IB_CM_REP_RCVD:
-	case IB_CM_MRA_REP_SENT:
-		rej_msg->local_comm_id = cm_id_priv->id.local_id;
-		cm_rej_set_msg_rejected(rej_msg, CM_MSG_RESPONSE_REP);
-		break;
-	default:
-		rej_msg->local_comm_id = cm_id_priv->id.local_id;
-		cm_rej_set_msg_rejected(rej_msg, CM_MSG_RESPONSE_OTHER);
-		break;
-	}
-
-	rej_msg->reason = reason;
-	if (ari && ari_length) {
-		cm_rej_set_reject_info_len(rej_msg, ari_length);
-		memcpy(rej_msg->ari, ari, ari_length);
-	}
-
-	if (private_data && private_data_len)
-		memcpy(rej_msg->private_data, private_data, private_data_len);
-}
-
 int ib_send_cm_rej(struct ib_cm_id *cm_id,
 		   enum ib_cm_rej_reason reason,
 		   void *ari,
@@ -1895,48 +1997,6 @@ out:
 	return -EINVAL;
 }
 
-static void cm_format_mra(struct cm_mra_msg *mra_msg,
-			  struct cm_id_private *cm_id_priv,
-			  u8 service_timeout,
-			  const void *private_data,
-			  u8 private_data_len)
-{
-	enum cm_msg_sequence msg_sequence;
-	unsigned long flags;
-	enum cm_msg_response msg_mraed;
-
-	spin_lock_irqsave(&cm_id_priv->lock, flags);
-	switch(cm_id_priv->id.state) {
-	case IB_CM_REQ_RCVD:
-		msg_sequence = CM_MSG_SEQUENCE_REQ;
-		msg_mraed = CM_MSG_RESPONSE_REQ;
-		break;
-	case IB_CM_REP_RCVD:
-		msg_sequence = CM_MSG_SEQUENCE_REQ;
-		msg_mraed = CM_MSG_RESPONSE_REP;
-		break;
-	case IB_CM_ESTABLISHED:
-		msg_sequence = CM_MSG_SEQUENCE_LAP;
-		msg_mraed = CM_MSG_RESPONSE_OTHER;
-		break;
-	default:
-		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
-		return;
-	}
-	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
-	/* todo: TID should matched REQ or LAP */
-	cm_format_mad_hdr(&mra_msg->hdr, CM_MRA_ATTR_ID,
-			  cm_form_tid(cm_id_priv, msg_sequence));
-	cm_mra_set_msg_mraed(mra_msg, msg_mraed);
-
-	mra_msg->local_comm_id = cm_id_priv->id.local_id;
-	mra_msg->remote_comm_id = cm_id_priv->id.remote_id;
-	cm_mra_set_service_timeout(mra_msg, service_timeout);
-
-	if (private_data && private_data_len)
-		memcpy(mra_msg->private_data, private_data, private_data_len);
-}
-
 int ib_send_cm_mra(struct ib_cm_id *cm_id,
 		   u8 service_timeout,
 		   const void *private_data,
@@ -1954,44 +2014,50 @@ int ib_send_cm_mra(struct ib_cm_id *cm_i
 	cm_id_priv = container_of(cm_id, struct cm_id_private, id);
 	ret = cm_alloc_msg(cm_id_priv, &msg);
 	if (ret)
-		goto out;
-
-	cm_format_mra((struct cm_mra_msg *) msg->mad, cm_id_priv,
-		      service_timeout, private_data, private_data_len);
+		return ret;
 
 	spin_lock_irqsave(&cm_id_priv->lock, flags);
-	if (cm_id_priv->id.state == IB_CM_REQ_RCVD ||
-	    cm_id_priv->id.state == IB_CM_REP_RCVD ||
-	    (cm_id_priv->id.state == IB_CM_ESTABLISHED &&
-	     cm_id_priv->id.lap_state == IB_CM_LAP_RCVD)) {
-
+	switch(cm_id_priv->id.state) {
+	case IB_CM_REQ_RCVD:
+		cm_format_mra((struct cm_mra_msg *) msg->mad, cm_id_priv,
+			      CM_MSG_RESPONSE_REQ, service_timeout,
+			      private_data, private_data_len);
 		ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,
 				       &msg->send_wr, &bad_send_wr);
-	} else {
-		ret = -EINVAL;
-	}
-
-	if (ret)  {
-		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
-		cm_free_msg(msg);
-		goto out;
-	}
-
-	switch (cm_id_priv->id.state) {
-	case IB_CM_REQ_RCVD:
+		if (ret)
+			goto error;
 		cm_id->state = IB_CM_MRA_REQ_SENT;
 		break;
 	case IB_CM_REP_RCVD:
+		cm_format_mra((struct cm_mra_msg *) msg->mad, cm_id_priv,
+			      CM_MSG_RESPONSE_REP, service_timeout,
+			      private_data, private_data_len);
+		ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,
+				       &msg->send_wr, &bad_send_wr);
+		if (ret)
+			goto error;
 		cm_id->state = IB_CM_MRA_REP_SENT;
 		break;
 	case IB_CM_ESTABLISHED:
-		cm_id_priv->id.lap_state = IB_CM_MRA_LAP_SENT;
+		cm_format_mra((struct cm_mra_msg *) msg->mad, cm_id_priv,
+			      CM_MSG_RESPONSE_OTHER, service_timeout,
+			      private_data, private_data_len);
+		ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,
+				       &msg->send_wr, &bad_send_wr);
+		if (ret)
+			goto error;
+		cm_id->lap_state = IB_CM_MRA_LAP_SENT;
 		break;
 	default:
-		break;
+		ret = -EINVAL;
+		goto error;
 	}
+	cm_id_priv->service_timeout = service_timeout;
 	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
-out:
+	return 0;
+
+error:	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+	cm_free_msg(msg);
 	return ret;
 }
 EXPORT_SYMBOL(ib_send_cm_mra);
@@ -2177,6 +2243,8 @@ static int cm_lap_handler(struct cm_work
 	struct cm_id_private *cm_id_priv;
 	struct cm_lap_msg *lap_msg;
 	struct ib_cm_lap_event_param *param;
+	struct ib_mad_send_buf *msg = NULL;
+	struct ib_send_wr *bad_send_wr;
 	unsigned long flags;
 	int ret;
 
@@ -2193,11 +2261,31 @@ static int cm_lap_handler(struct cm_work
 	work->cm_event.private_data = &lap_msg->private_data;
 
 	spin_lock_irqsave(&cm_id_priv->lock, flags);
-	if (cm_id_priv->id.state != IB_CM_ESTABLISHED &&
-	    cm_id_priv->id.lap_state != IB_CM_LAP_IDLE) {
+	if (cm_id_priv->id.state != IB_CM_ESTABLISHED)
+		goto unlock;
+	
+	switch (cm_id_priv->id.lap_state) {
+	case IB_CM_LAP_IDLE:
+		break;
+	case IB_CM_MRA_LAP_SENT:
+		if (cm_alloc_response_msg(work->port, work->mad_recv_wc, &msg))
+			goto unlock;
+
+		cm_format_mra((struct cm_mra_msg *) msg->mad, cm_id_priv,
+			      CM_MSG_RESPONSE_OTHER,
+			      cm_id_priv->service_timeout,
+			      cm_id_priv->private_data,
+			      cm_id_priv->private_data_len);
 		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
-		goto out;
+
+		if (ib_post_send_mad(cm_id_priv->av.port->mad_agent,
+				     &msg->send_wr, &bad_send_wr))
+			cm_free_msg(msg);
+		goto deref;
+	default:
+		goto unlock;
 	}
+
 	cm_id_priv->id.lap_state = IB_CM_LAP_RCVD;
 	ret = atomic_inc_and_test(&cm_id_priv->work_count);
 	if (!ret)
@@ -2209,8 +2297,9 @@ static int cm_lap_handler(struct cm_work
 	else
 		cm_deref_id(cm_id_priv);
 	return 0;
-out:
-	cm_deref_id(cm_id_priv);
+
+unlock:	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+deref:	cm_deref_id(cm_id_priv);
 	return -EINVAL;
 }
 






More information about the general mailing list