[openib-general] [PATCH] [CM] add MRA handling to CM

Sean Hefty sean.hefty at intel.com
Wed May 18 15:30:33 PDT 2005


The following patch adds MRA receive handling to the CM, and fixes
a bug where the state checking was reversed when sending the MRA.

Note: if the MRA is lost, it will not be resent.  That support will
come in a separate patch.

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


Index: cm.c
===================================================================
--- cm.c	(revision 2402)
+++ cm.c	(working copy)
@@ -1712,7 +1712,12 @@ static void cm_format_rej(struct cm_rej_
 		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;
@@ -1826,7 +1831,9 @@ static struct cm_id_private * cm_acquire
 				cm_id_priv = NULL;
 		}
 		spin_unlock_irqrestore(&cm.lock, flags);
-	} else
+	} else if (cm_rej_get_msg_rejected(rej_msg) == CM_MSG_RESPONSE_REQ)
+		cm_id_priv = cm_acquire_id(rej_msg->remote_comm_id, 0);
+	else
 		cm_id_priv = cm_acquire_id(rej_msg->remote_comm_id, remote_id);
 
 	return cm_id_priv;
@@ -1849,14 +1856,14 @@ static int cm_rej_handler(struct cm_work
 	spin_lock_irqsave(&cm_id_priv->lock, flags);
 	switch (cm_id_priv->id.state) {
 	case IB_CM_REQ_SENT:
+	case IB_CM_MRA_REQ_RCVD:
 	case IB_CM_REP_SENT:
+	case IB_CM_MRA_REP_RCVD:
 		ib_cancel_mad(cm_id_priv->av.port->mad_agent,
 			      (unsigned long) cm_id_priv->msg);
 		/* fall through */
 	case IB_CM_REQ_RCVD:
 	case IB_CM_MRA_REQ_SENT:
-	case IB_CM_MRA_REQ_RCVD:
-	case IB_CM_MRA_REP_RCVD:
 		if (rej_msg->reason == IB_CM_REJ_STALE_CONN)
 			cm_enter_timewait(cm_id_priv);
 		else
@@ -1957,10 +1964,10 @@ int ib_send_cm_mra(struct ib_cm_id *cm_i
 		      service_timeout, private_data, private_data_len);
 
 	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)) {
+	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)) {
 
 		ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,
 				       &msg->send_wr, &bad_send_wr);
@@ -1993,11 +2000,80 @@ out:
 }
 EXPORT_SYMBOL(ib_send_cm_mra);
 
+static struct cm_id_private * cm_acquire_mraed_id(struct cm_mra_msg *mra_msg)
+{
+	switch (cm_mra_get_msg_mraed(mra_msg)) {
+	case CM_MSG_RESPONSE_REQ:
+		return cm_acquire_id(mra_msg->remote_comm_id, 0);
+	case CM_MSG_RESPONSE_REP:
+	case CM_MSG_RESPONSE_OTHER:
+		return cm_acquire_id(mra_msg->remote_comm_id,
+				     mra_msg->local_comm_id);
+	default:
+		return NULL;
+	}
+}
+
 static int cm_mra_handler(struct cm_work *work)
 {
-	/* todo: write MRA handler */
-	/* todo: add timeout mechanism separate from retries for
-		receiver of MRA */
+	struct cm_id_private *cm_id_priv;
+	struct cm_mra_msg *mra_msg;
+	unsigned long flags;
+	int timeout, ret;
+
+	mra_msg = (struct cm_mra_msg *)work->mad_recv_wc->recv_buf.mad;
+	cm_id_priv = cm_acquire_mraed_id(mra_msg);
+	if (!cm_id_priv)
+		return -EINVAL;
+
+	work->cm_event.private_data = &mra_msg->private_data;
+	work->cm_event.param.mra_rcvd.service_timeout =
+					cm_mra_get_service_timeout(mra_msg);
+	timeout = cm_convert_to_ms(cm_mra_get_service_timeout(mra_msg));
+
+	spin_lock_irqsave(&cm_id_priv->lock, flags);
+	switch (cm_id_priv->id.state) {
+	case IB_CM_REQ_SENT:
+		if (cm_mra_get_msg_mraed(mra_msg) != CM_MSG_RESPONSE_REQ ||
+		    ib_modify_mad(cm_id_priv->av.port->mad_agent,
+				  (unsigned long) cm_id_priv->msg, timeout))
+			goto out;
+		cm_id_priv->id.state = IB_CM_MRA_REQ_RCVD;
+		break;
+	case IB_CM_REP_SENT:
+		if (cm_mra_get_msg_mraed(mra_msg) != CM_MSG_RESPONSE_REP ||
+		    ib_modify_mad(cm_id_priv->av.port->mad_agent,
+				  (unsigned long) cm_id_priv->msg, timeout))
+			goto out;
+		cm_id_priv->id.state = IB_CM_MRA_REP_RCVD;
+		break;
+	case IB_CM_ESTABLISHED:
+		if (cm_mra_get_msg_mraed(mra_msg) != CM_MSG_RESPONSE_OTHER ||
+		    cm_id_priv->id.lap_state != IB_CM_LAP_SENT ||
+		    ib_modify_mad(cm_id_priv->av.port->mad_agent,
+				  (unsigned long) cm_id_priv->msg, timeout))
+			goto out;
+		cm_id_priv->id.lap_state = IB_CM_MRA_LAP_RCVD;
+		break;
+	default:
+		goto out;
+	}
+
+	cm_id_priv->msg->context[1] = (void *) (unsigned long)
+				      cm_id_priv->id.state;
+	ret = atomic_inc_and_test(&cm_id_priv->work_count);
+	if (!ret)
+		list_add_tail(&work->list, &cm_id_priv->work_list);
+	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+
+	if (ret)
+		cm_process_work(cm_id_priv, work);
+	else
+		cm_deref_id(cm_id_priv);
+	return 0;
+out:
+	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+	cm_deref_id(cm_id_priv);
 	return -EINVAL;
 }
 
@@ -2557,19 +2633,21 @@ static void cm_process_send_error(struct
 
 	memset(&cm_event, 0, sizeof cm_event);
 	cm_id_priv = msg->context[0];
-	state = (enum ib_cm_state) (unsigned long) msg->context[1];
 
 	/* Discard old sends or ones without a response. */
 	spin_lock_irqsave(&cm_id_priv->lock, flags);
+	state = (enum ib_cm_state) (unsigned long) msg->context[1];
 	if (msg != cm_id_priv->msg || state != cm_id_priv->id.state)
 		goto discard;
 
 	switch (state) {
 	case IB_CM_REQ_SENT:
+	case IB_CM_MRA_REQ_RCVD:
 		cm_reset_to_idle(cm_id_priv);
 		cm_event.event = IB_CM_REQ_ERROR;
 		break;
 	case IB_CM_REP_SENT:
+	case IB_CM_MRA_REP_RCVD:
 		cm_reset_to_idle(cm_id_priv);
 		cm_event.event = IB_CM_REP_ERROR;
 		break;






More information about the general mailing list