⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cm.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
		return ret;	}out:	spin_unlock_irqrestore(&cm_id_priv->lock, flags);	return ret;}EXPORT_SYMBOL(ib_send_cm_drep);static int cm_dreq_handler(struct cm_work *work){	struct cm_id_private *cm_id_priv;	struct cm_dreq_msg *dreq_msg;	struct ib_mad_send_buf *msg = NULL;	unsigned long flags;	int ret;	dreq_msg = (struct cm_dreq_msg *)work->mad_recv_wc->recv_buf.mad;	cm_id_priv = cm_acquire_id(dreq_msg->remote_comm_id,				   dreq_msg->local_comm_id);	if (!cm_id_priv)		return -EINVAL;	work->cm_event.private_data = &dreq_msg->private_data;	spin_lock_irqsave(&cm_id_priv->lock, flags);	if (cm_id_priv->local_qpn != cm_dreq_get_remote_qpn(dreq_msg))		goto unlock;	switch (cm_id_priv->id.state) {	case IB_CM_REP_SENT:	case IB_CM_DREQ_SENT:		ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);		break;	case IB_CM_ESTABLISHED:	case IB_CM_MRA_REP_RCVD:		break;	case IB_CM_TIMEWAIT:		if (cm_alloc_response_msg(work->port, work->mad_recv_wc, &msg))			goto unlock;		cm_format_drep((struct cm_drep_msg *) msg->mad, cm_id_priv,			       cm_id_priv->private_data,			       cm_id_priv->private_data_len);		spin_unlock_irqrestore(&cm_id_priv->lock, flags);		if (ib_post_send_mad(msg, NULL))			cm_free_msg(msg);		goto deref;	default:		goto unlock;	}	cm_id_priv->id.state = IB_CM_DREQ_RCVD;	cm_id_priv->tid = dreq_msg->hdr.tid;	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;unlock:	spin_unlock_irqrestore(&cm_id_priv->lock, flags);deref:	cm_deref_id(cm_id_priv);	return -EINVAL;}static int cm_drep_handler(struct cm_work *work){	struct cm_id_private *cm_id_priv;	struct cm_drep_msg *drep_msg;	unsigned long flags;	int ret;	drep_msg = (struct cm_drep_msg *)work->mad_recv_wc->recv_buf.mad;	cm_id_priv = cm_acquire_id(drep_msg->remote_comm_id,				   drep_msg->local_comm_id);	if (!cm_id_priv)		return -EINVAL;	work->cm_event.private_data = &drep_msg->private_data;	spin_lock_irqsave(&cm_id_priv->lock, flags);	if (cm_id_priv->id.state != IB_CM_DREQ_SENT &&	    cm_id_priv->id.state != IB_CM_DREQ_RCVD) {		spin_unlock_irqrestore(&cm_id_priv->lock, flags);		goto out;	}	cm_enter_timewait(cm_id_priv);	ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);	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:	cm_deref_id(cm_id_priv);	return -EINVAL;}int ib_send_cm_rej(struct ib_cm_id *cm_id,		   enum ib_cm_rej_reason reason,		   void *ari,		   u8 ari_length,		   const void *private_data,		   u8 private_data_len){	struct cm_id_private *cm_id_priv;	struct ib_mad_send_buf *msg;	unsigned long flags;	int ret;	if ((private_data && private_data_len > IB_CM_REJ_PRIVATE_DATA_SIZE) ||	    (ari && ari_length > IB_CM_REJ_ARI_LENGTH))		return -EINVAL;	cm_id_priv = container_of(cm_id, struct cm_id_private, id);	spin_lock_irqsave(&cm_id_priv->lock, flags);	switch (cm_id->state) {	case IB_CM_REQ_SENT:	case IB_CM_MRA_REQ_RCVD:	case IB_CM_REQ_RCVD:	case IB_CM_MRA_REQ_SENT:	case IB_CM_REP_RCVD:	case IB_CM_MRA_REP_SENT:		ret = cm_alloc_msg(cm_id_priv, &msg);		if (!ret)			cm_format_rej((struct cm_rej_msg *) msg->mad,				      cm_id_priv, reason, ari, ari_length,				      private_data, private_data_len);		cm_reset_to_idle(cm_id_priv);		break;	case IB_CM_REP_SENT:	case IB_CM_MRA_REP_RCVD:		ret = cm_alloc_msg(cm_id_priv, &msg);		if (!ret)			cm_format_rej((struct cm_rej_msg *) msg->mad,				      cm_id_priv, reason, ari, ari_length,				      private_data, private_data_len);		cm_enter_timewait(cm_id_priv);		break;	default:		ret = -EINVAL;		goto out;	}	if (ret)		goto out;	ret = ib_post_send_mad(msg, NULL);	if (ret)		cm_free_msg(msg);out:	spin_unlock_irqrestore(&cm_id_priv->lock, flags);	return ret;}EXPORT_SYMBOL(ib_send_cm_rej);static void cm_format_rej_event(struct cm_work *work){	struct cm_rej_msg *rej_msg;	struct ib_cm_rej_event_param *param;	rej_msg = (struct cm_rej_msg *)work->mad_recv_wc->recv_buf.mad;	param = &work->cm_event.param.rej_rcvd;	param->ari = rej_msg->ari;	param->ari_length = cm_rej_get_reject_info_len(rej_msg);	param->reason = __be16_to_cpu(rej_msg->reason);	work->cm_event.private_data = &rej_msg->private_data;}static struct cm_id_private * cm_acquire_rejected_id(struct cm_rej_msg *rej_msg){	struct cm_timewait_info *timewait_info;	struct cm_id_private *cm_id_priv;	unsigned long flags;	__be32 remote_id;	remote_id = rej_msg->local_comm_id;	if (__be16_to_cpu(rej_msg->reason) == IB_CM_REJ_TIMEOUT) {		spin_lock_irqsave(&cm.lock, flags);		timewait_info = cm_find_remote_id( *((__be64 *) rej_msg->ari),						  remote_id);		if (!timewait_info) {			spin_unlock_irqrestore(&cm.lock, flags);			return NULL;		}		cm_id_priv = idr_find(&cm.local_id_table,				      (__force int) timewait_info->work.local_id);		if (cm_id_priv) {			if (cm_id_priv->id.remote_id == remote_id)				atomic_inc(&cm_id_priv->refcount);			else				cm_id_priv = NULL;		}		spin_unlock_irqrestore(&cm.lock, flags);	} 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;}static int cm_rej_handler(struct cm_work *work){	struct cm_id_private *cm_id_priv;	struct cm_rej_msg *rej_msg;	unsigned long flags;	int ret;	rej_msg = (struct cm_rej_msg *)work->mad_recv_wc->recv_buf.mad;	cm_id_priv = cm_acquire_rejected_id(rej_msg);	if (!cm_id_priv)		return -EINVAL;	cm_format_rej_event(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, cm_id_priv->msg);		/* fall through */	case IB_CM_REQ_RCVD:	case IB_CM_MRA_REQ_SENT:		if (__be16_to_cpu(rej_msg->reason) == IB_CM_REJ_STALE_CONN)			cm_enter_timewait(cm_id_priv);		else			cm_reset_to_idle(cm_id_priv);		break;	case IB_CM_DREQ_SENT:		ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);		/* fall through */	case IB_CM_REP_RCVD:	case IB_CM_MRA_REP_SENT:	case IB_CM_ESTABLISHED:		cm_enter_timewait(cm_id_priv);		break;	default:		spin_unlock_irqrestore(&cm_id_priv->lock, flags);		ret = -EINVAL;		goto out;	}	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:	cm_deref_id(cm_id_priv);	return -EINVAL;}int ib_send_cm_mra(struct ib_cm_id *cm_id,		   u8 service_timeout,		   const void *private_data,		   u8 private_data_len){	struct cm_id_private *cm_id_priv;	struct ib_mad_send_buf *msg;	void *data;	unsigned long flags;	int ret;	if (private_data && private_data_len > IB_CM_MRA_PRIVATE_DATA_SIZE)		return -EINVAL;	data = cm_copy_private_data(private_data, private_data_len);	if (IS_ERR(data))		return PTR_ERR(data);	cm_id_priv = container_of(cm_id, struct cm_id_private, id);	spin_lock_irqsave(&cm_id_priv->lock, flags);	switch(cm_id_priv->id.state) {	case IB_CM_REQ_RCVD:		ret = cm_alloc_msg(cm_id_priv, &msg);		if (ret)			goto error1;		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(msg, NULL);		if (ret)			goto error2;		cm_id->state = IB_CM_MRA_REQ_SENT;		break;	case IB_CM_REP_RCVD:		ret = cm_alloc_msg(cm_id_priv, &msg);		if (ret)			goto error1;		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(msg, NULL);		if (ret)			goto error2;		cm_id->state = IB_CM_MRA_REP_SENT;		break;	case IB_CM_ESTABLISHED:		ret = cm_alloc_msg(cm_id_priv, &msg);		if (ret)			goto error1;		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(msg, NULL);		if (ret)			goto error2;		cm_id->lap_state = IB_CM_MRA_LAP_SENT;		break;	default:		ret = -EINVAL;		goto error1;	}	cm_id_priv->service_timeout = service_timeout;	cm_set_private_data(cm_id_priv, data, private_data_len);	spin_unlock_irqrestore(&cm_id_priv->lock, flags);	return 0;error1:	spin_unlock_irqrestore(&cm_id_priv->lock, flags);	kfree(data);	return ret;error2:	spin_unlock_irqrestore(&cm_id_priv->lock, flags);	kfree(data);	cm_free_msg(msg);	return ret;}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){	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)) +		  cm_convert_to_ms(cm_id_priv->av.packet_life_time);	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,				  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,				  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,				  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;}static void cm_format_lap(struct cm_lap_msg *lap_msg,			  struct cm_id_private *cm_id_priv,			  struct ib_sa_path_rec *alternate_path,			  const void *private_data,			  u8 private_data_len){	cm_format_mad_hdr(&lap_msg->hdr, CM_LAP_ATTR_ID,			  cm_form_tid(cm_id_priv, CM_MSG_SEQUENCE_LAP));	lap_msg->local_comm_id = cm_id_priv->id.local_id;	lap_msg->remote_comm_id = cm_id_priv->id.remote_id;	cm_lap_set_remote_qpn(lap_msg, cm_id_priv->remote_qpn);	/* todo: ne

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -