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

📄 cm.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
		goto out;	}	spin_unlock_irqrestore(&cm_id_priv->lock, flags);	cm_id_priv->timewait_info = cm_create_timewait_info(cm_id_priv->							    id.local_id);	if (IS_ERR(cm_id_priv->timewait_info))		goto out;	ret = cm_init_av_by_path(param->primary_path, &cm_id_priv->av);	if (ret)		goto error1;	if (param->alternate_path) {		ret = cm_init_av_by_path(param->alternate_path,					 &cm_id_priv->alt_av);		if (ret)			goto error1;	}	cm_id->service_id = param->service_id;	cm_id->service_mask = __constant_cpu_to_be64(~0ULL);	cm_id_priv->timeout_ms = cm_convert_to_ms(				    param->primary_path->packet_life_time) * 2 +				 cm_convert_to_ms(				    param->remote_cm_response_timeout);	cm_id_priv->max_cm_retries = param->max_cm_retries;	cm_id_priv->initiator_depth = param->initiator_depth;	cm_id_priv->responder_resources = param->responder_resources;	cm_id_priv->retry_count = param->retry_count;	cm_id_priv->path_mtu = param->primary_path->mtu;	cm_id_priv->qp_type = param->qp_type;	ret = cm_alloc_msg(cm_id_priv, &cm_id_priv->msg);	if (ret)		goto error1;	req_msg = (struct cm_req_msg *) cm_id_priv->msg->mad;	cm_format_req(req_msg, cm_id_priv, param);	cm_id_priv->tid = req_msg->hdr.tid;	cm_id_priv->msg->timeout_ms = cm_id_priv->timeout_ms;	cm_id_priv->msg->context[1] = (void *) (unsigned long) IB_CM_REQ_SENT;	cm_id_priv->local_qpn = cm_req_get_local_qpn(req_msg);	cm_id_priv->rq_psn = cm_req_get_starting_psn(req_msg);	cm_id_priv->local_ack_timeout =				cm_req_get_primary_local_ack_timeout(req_msg);	spin_lock_irqsave(&cm_id_priv->lock, flags);	ret = ib_post_send_mad(cm_id_priv->msg, NULL);	if (ret) {		spin_unlock_irqrestore(&cm_id_priv->lock, flags);		goto error2;	}	BUG_ON(cm_id->state != IB_CM_IDLE);	cm_id->state = IB_CM_REQ_SENT;	spin_unlock_irqrestore(&cm_id_priv->lock, flags);	return 0;error2:	cm_free_msg(cm_id_priv->msg);error1:	kfree(cm_id_priv->timewait_info);out:	return ret;}EXPORT_SYMBOL(ib_send_cm_req);static int cm_issue_rej(struct cm_port *port,			struct ib_mad_recv_wc *mad_recv_wc,			enum ib_cm_rej_reason reason,			enum cm_msg_response msg_rejected,			void *ari, u8 ari_length){	struct ib_mad_send_buf *msg = NULL;	struct cm_rej_msg *rej_msg, *rcv_msg;	int ret;	ret = cm_alloc_response_msg(port, mad_recv_wc, &msg);	if (ret)		return ret;	/* We just need common CM header information.  Cast to any message. */	rcv_msg = (struct cm_rej_msg *) mad_recv_wc->recv_buf.mad;	rej_msg = (struct cm_rej_msg *) msg->mad;	cm_format_mad_hdr(&rej_msg->hdr, CM_REJ_ATTR_ID, rcv_msg->hdr.tid);	rej_msg->remote_comm_id = rcv_msg->local_comm_id;	rej_msg->local_comm_id = rcv_msg->remote_comm_id;	cm_rej_set_msg_rejected(rej_msg, msg_rejected);	rej_msg->reason = cpu_to_be16(reason);	if (ari && ari_length) {		cm_rej_set_reject_info_len(rej_msg, ari_length);		memcpy(rej_msg->ari, ari, ari_length);	}	ret = ib_post_send_mad(msg, NULL);	if (ret)		cm_free_msg(msg);	return ret;}static inline int cm_is_active_peer(__be64 local_ca_guid, __be64 remote_ca_guid,				    __be32 local_qpn, __be32 remote_qpn){	return (be64_to_cpu(local_ca_guid) > be64_to_cpu(remote_ca_guid) ||		((local_ca_guid == remote_ca_guid) &&		 (be32_to_cpu(local_qpn) > be32_to_cpu(remote_qpn))));}static inline void cm_format_paths_from_req(struct cm_req_msg *req_msg,					    struct ib_sa_path_rec *primary_path,					    struct ib_sa_path_rec *alt_path){	memset(primary_path, 0, sizeof *primary_path);	primary_path->dgid = req_msg->primary_local_gid;	primary_path->sgid = req_msg->primary_remote_gid;	primary_path->dlid = req_msg->primary_local_lid;	primary_path->slid = req_msg->primary_remote_lid;	primary_path->flow_label = cm_req_get_primary_flow_label(req_msg);	primary_path->hop_limit = req_msg->primary_hop_limit;	primary_path->traffic_class = req_msg->primary_traffic_class;	primary_path->reversible = 1;	primary_path->pkey = req_msg->pkey;	primary_path->sl = cm_req_get_primary_sl(req_msg);	primary_path->mtu_selector = IB_SA_EQ;	primary_path->mtu = cm_req_get_path_mtu(req_msg);	primary_path->rate_selector = IB_SA_EQ;	primary_path->rate = cm_req_get_primary_packet_rate(req_msg);	primary_path->packet_life_time_selector = IB_SA_EQ;	primary_path->packet_life_time =		cm_req_get_primary_local_ack_timeout(req_msg);	primary_path->packet_life_time -= (primary_path->packet_life_time > 0);	if (req_msg->alt_local_lid) {		memset(alt_path, 0, sizeof *alt_path);		alt_path->dgid = req_msg->alt_local_gid;		alt_path->sgid = req_msg->alt_remote_gid;		alt_path->dlid = req_msg->alt_local_lid;		alt_path->slid = req_msg->alt_remote_lid;		alt_path->flow_label = cm_req_get_alt_flow_label(req_msg);		alt_path->hop_limit = req_msg->alt_hop_limit;		alt_path->traffic_class = req_msg->alt_traffic_class;		alt_path->reversible = 1;		alt_path->pkey = req_msg->pkey;		alt_path->sl = cm_req_get_alt_sl(req_msg);		alt_path->mtu_selector = IB_SA_EQ;		alt_path->mtu = cm_req_get_path_mtu(req_msg);		alt_path->rate_selector = IB_SA_EQ;		alt_path->rate = cm_req_get_alt_packet_rate(req_msg);		alt_path->packet_life_time_selector = IB_SA_EQ;		alt_path->packet_life_time =			cm_req_get_alt_local_ack_timeout(req_msg);		alt_path->packet_life_time -= (alt_path->packet_life_time > 0);	}}static void cm_format_req_event(struct cm_work *work,				struct cm_id_private *cm_id_priv,				struct ib_cm_id *listen_id){	struct cm_req_msg *req_msg;	struct ib_cm_req_event_param *param;	req_msg = (struct cm_req_msg *)work->mad_recv_wc->recv_buf.mad;	param = &work->cm_event.param.req_rcvd;	param->listen_id = listen_id;	param->port = cm_id_priv->av.port->port_num;	param->primary_path = &work->path[0];	if (req_msg->alt_local_lid)		param->alternate_path = &work->path[1];	else		param->alternate_path = NULL;	param->remote_ca_guid = req_msg->local_ca_guid;	param->remote_qkey = be32_to_cpu(req_msg->local_qkey);	param->remote_qpn = be32_to_cpu(cm_req_get_local_qpn(req_msg));	param->qp_type = cm_req_get_qp_type(req_msg);	param->starting_psn = be32_to_cpu(cm_req_get_starting_psn(req_msg));	param->responder_resources = cm_req_get_init_depth(req_msg);	param->initiator_depth = cm_req_get_resp_res(req_msg);	param->local_cm_response_timeout =					cm_req_get_remote_resp_timeout(req_msg);	param->flow_control = cm_req_get_flow_ctrl(req_msg);	param->remote_cm_response_timeout =					cm_req_get_local_resp_timeout(req_msg);	param->retry_count = cm_req_get_retry_count(req_msg);	param->rnr_retry_count = cm_req_get_rnr_retry_count(req_msg);	param->srq = cm_req_get_srq(req_msg);	work->cm_event.private_data = &req_msg->private_data;}static void cm_process_work(struct cm_id_private *cm_id_priv,			    struct cm_work *work){	unsigned long flags;	int ret;	/* We will typically only have the current event to report. */	ret = cm_id_priv->id.cm_handler(&cm_id_priv->id, &work->cm_event);	cm_free_work(work);	while (!ret && !atomic_add_negative(-1, &cm_id_priv->work_count)) {		spin_lock_irqsave(&cm_id_priv->lock, flags);		work = cm_dequeue_work(cm_id_priv);		spin_unlock_irqrestore(&cm_id_priv->lock, flags);		BUG_ON(!work);		ret = cm_id_priv->id.cm_handler(&cm_id_priv->id,						&work->cm_event);		cm_free_work(work);	}	cm_deref_id(cm_id_priv);	if (ret)		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){	cm_format_mad_hdr(&mra_msg->hdr, CM_MRA_ATTR_ID, cm_id_priv->tid);	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){	cm_format_mad_hdr(&rej_msg->hdr, CM_REJ_ATTR_ID, cm_id_priv->tid);	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 = cpu_to_be16(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;	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(msg, NULL);	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(cm_id_priv->id.device,					   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;	int ret;	req_msg = (struct cm_req_msg *)work->mad_recv_wc->recv_buf.mad;	cm_id = ib_create_cm_id(work->port->cm_dev->device, NULL, NULL);	if (IS_ERR(cm_id))		return PTR_ERR(cm_id);	cm_id_priv = container_of(cm_id, struct cm_id_private, id);	cm_id_priv->id.remote_id = req_msg->local_comm_id;	cm_init_av_for_response(work->port, work->mad_recv_wc->wc,				&cm_id_priv->av);	cm_id_priv->timewait_info = cm_create_timewait_info(cm_id_priv->							    id.local_id);	if (IS_ERR(cm_id_priv->timewait_info)) {		ret = PTR_ERR(cm_id_priv->timewait_info);		goto error1;	}	cm_id_priv->timewait_info->work.remote_id = req_msg->local_comm_id;	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);	listen_cm_id_priv = cm_match_req(work, cm_id_priv);	if (!listen_cm_id_priv) {		ret = -EINVAL;		goto error2;	}	cm_id_priv->id.cm_handler = listen_cm_id_priv->id.cm_handler;	cm_id_priv->id.context = listen_cm_id_priv->id.context;	cm_id_priv->id.service_id = req_msg->service_id;	cm_id_priv->id.service_mask = __constant_cpu_to_be64(~0ULL);	cm_format_paths_from_req(req_msg, &work->path[0], &work->path[1]);	ret = cm_init_av_by_path(&work->path[0], &cm_id_priv->av);	if (ret)		goto error3;	if (req_msg->alt_local_lid) {		ret = cm_init_av_by_path(&work->path[1], &cm_id_priv->alt_av);		if (ret)			goto error3;	}	cm_id_priv->tid = req_msg->hdr.tid;	cm_id_priv->timeout_ms = cm_convert_to_ms(					cm_req_get_local_resp_timeout(req_msg));	cm_id_priv->max_cm_retries = cm_req_get_max_cm_retries(req_msg);	cm_id_priv->remote_qpn = cm_req_get_local_qpn(req_msg);	cm_id_priv->initiator_depth = cm_req_get_resp_res(req_msg);	cm_id_priv->responder_resources = cm_req_get_init_depth(req_msg);	cm_id_priv->path_mtu = cm_req_get_path_mtu(req_msg);	cm_id_priv->sq_psn = cm_req_get_starting_psn(req_msg);	cm_id_priv->local_ack_timeout =				cm_req_get_primary_local_ack_timeout(req_msg);	cm_id_priv->retry_count = cm_req_get_retry_count(req_msg);	cm_id_priv->rnr_retry_count = cm_req_get_rnr_retry_count(req_msg);	cm_id_priv->qp_type = cm_req_get_qp_type(req_msg);	cm_format_req_event(work, cm_id_priv, &listen_cm_id_priv->id);	cm_process_work(cm_id_priv, work);	cm_deref_id(listen_cm_id_priv);	return 0;error3:	atomic_dec(&cm_id_priv->refcount);	cm_deref_id(listen_cm_id_priv);	cm_cleanup_timewait(cm_id_priv->timewait_info);error2:	kfree(cm_id_priv->timewait_info);	cm_id_priv->timewait_info = NULL;error1:	ib_destroy_cm_id(&cm_id_priv->id);	return ret;}static void cm_format_rep(struct cm_rep_msg *rep_msg,			  struct cm_id_private *cm_id_priv,			  struct ib_cm_rep_param *param){	cm_format_mad_hdr(&rep_msg->hdr, CM_REP_ATTR_ID, cm_id_priv->tid);	rep_msg->local_comm_id = cm_id_priv->id.local_id;	rep_msg->remote_comm_id = cm_id_priv->id.remote_id;	cm_rep_set_local_qpn(rep_msg, cpu_to_be32(param->qp_num));	cm_rep_set_starting_psn(rep_msg, cpu_to_be32(param->starting_psn));	rep_msg->resp_resources = param->responder_resources;	rep_msg->initiator_depth = param->initiator_depth;

⌨️ 快捷键说明

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