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

📄 cm.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	atomic_inc(&cm_id_priv->refcount);	cm_id_priv->id.state = IB_CM_REQ_RCVD;	atomic_inc(&cm_id_priv->work_count);	spin_unlock_irq(&cm.lock);out:	return listen_cm_id_priv;}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,				work->mad_recv_wc->recv_buf.grh,				&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 destroy;	}	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;		kfree(cm_id_priv->timewait_info);		goto destroy;	}	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) {		ib_get_cached_gid(work->port->cm_dev->device,				  work->port->port_num, 0, &work->path[0].sgid);		ib_send_cm_rej(cm_id, IB_CM_REJ_INVALID_GID,			       &work->path[0].sgid, sizeof work->path[0].sgid,			       NULL, 0);		goto rejected;	}	if (req_msg->alt_local_lid) {		ret = cm_init_av_by_path(&work->path[1], &cm_id_priv->alt_av);		if (ret) {			ib_send_cm_rej(cm_id, IB_CM_REJ_INVALID_ALT_GID,				       &work->path[0].sgid,				       sizeof work->path[0].sgid, NULL, 0);			goto rejected;		}	}	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->pkey = req_msg->pkey;	cm_id_priv->sq_psn = cm_req_get_starting_psn(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;rejected:	atomic_dec(&cm_id_priv->refcount);	cm_deref_id(listen_cm_id_priv);destroy:	ib_destroy_cm_id(cm_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;	cm_rep_set_target_ack_delay(rep_msg,				    cm_id_priv->av.port->cm_dev->ack_delay);	cm_rep_set_failover(rep_msg, param->failover_accepted);	cm_rep_set_flow_ctrl(rep_msg, param->flow_control);	cm_rep_set_rnr_retry_count(rep_msg, param->rnr_retry_count);	cm_rep_set_srq(rep_msg, param->srq);	rep_msg->local_ca_guid = cm_id_priv->id.device->node_guid;	if (param->private_data && param->private_data_len)		memcpy(rep_msg->private_data, param->private_data,		       param->private_data_len);}int ib_send_cm_rep(struct ib_cm_id *cm_id,		   struct ib_cm_rep_param *param){	struct cm_id_private *cm_id_priv;	struct ib_mad_send_buf *msg;	struct cm_rep_msg *rep_msg;	unsigned long flags;	int ret;	if (param->private_data &&	    param->private_data_len > IB_CM_REP_PRIVATE_DATA_SIZE)		return -EINVAL;	cm_id_priv = container_of(cm_id, struct cm_id_private, id);	spin_lock_irqsave(&cm_id_priv->lock, flags);	if (cm_id->state != IB_CM_REQ_RCVD &&	    cm_id->state != IB_CM_MRA_REQ_SENT) {		ret = -EINVAL;		goto out;	}	ret = cm_alloc_msg(cm_id_priv, &msg);	if (ret)		goto out;	rep_msg = (struct cm_rep_msg *) msg->mad;	cm_format_rep(rep_msg, cm_id_priv, param);	msg->timeout_ms = cm_id_priv->timeout_ms;	msg->context[1] = (void *) (unsigned long) IB_CM_REP_SENT;	ret = ib_post_send_mad(msg, NULL);	if (ret) {		spin_unlock_irqrestore(&cm_id_priv->lock, flags);		cm_free_msg(msg);		return ret;	}	cm_id->state = IB_CM_REP_SENT;	cm_id_priv->msg = msg;	cm_id_priv->initiator_depth = param->initiator_depth;	cm_id_priv->responder_resources = param->responder_resources;	cm_id_priv->rq_psn = cm_rep_get_starting_psn(rep_msg);	cm_id_priv->local_qpn = cm_rep_get_local_qpn(rep_msg);out:	spin_unlock_irqrestore(&cm_id_priv->lock, flags);	return ret;}EXPORT_SYMBOL(ib_send_cm_rep);static void cm_format_rtu(struct cm_rtu_msg *rtu_msg,			  struct cm_id_private *cm_id_priv,			  const void *private_data,			  u8 private_data_len){	cm_format_mad_hdr(&rtu_msg->hdr, CM_RTU_ATTR_ID, cm_id_priv->tid);	rtu_msg->local_comm_id = cm_id_priv->id.local_id;	rtu_msg->remote_comm_id = cm_id_priv->id.remote_id;	if (private_data && private_data_len)		memcpy(rtu_msg->private_data, private_data, private_data_len);}int ib_send_cm_rtu(struct ib_cm_id *cm_id,		   const void *private_data,		   u8 private_data_len){	struct cm_id_private *cm_id_priv;	struct ib_mad_send_buf *msg;	unsigned long flags;	void *data;	int ret;	if (private_data && private_data_len > IB_CM_RTU_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);	if (cm_id->state != IB_CM_REP_RCVD &&	    cm_id->state != IB_CM_MRA_REP_SENT) {		ret = -EINVAL;		goto error;	}	ret = cm_alloc_msg(cm_id_priv, &msg);	if (ret)		goto error;	cm_format_rtu((struct cm_rtu_msg *) msg->mad, cm_id_priv,		      private_data, private_data_len);	ret = ib_post_send_mad(msg, NULL);	if (ret) {		spin_unlock_irqrestore(&cm_id_priv->lock, flags);		cm_free_msg(msg);		kfree(data);		return ret;	}	cm_id->state = IB_CM_ESTABLISHED;	cm_set_private_data(cm_id_priv, data, private_data_len);	spin_unlock_irqrestore(&cm_id_priv->lock, flags);	return 0;error:	spin_unlock_irqrestore(&cm_id_priv->lock, flags);	kfree(data);	return ret;}EXPORT_SYMBOL(ib_send_cm_rtu);static void cm_format_rep_event(struct cm_work *work){	struct cm_rep_msg *rep_msg;	struct ib_cm_rep_event_param *param;	rep_msg = (struct cm_rep_msg *)work->mad_recv_wc->recv_buf.mad;	param = &work->cm_event.param.rep_rcvd;	param->remote_ca_guid = rep_msg->local_ca_guid;	param->remote_qkey = be32_to_cpu(rep_msg->local_qkey);	param->remote_qpn = be32_to_cpu(cm_rep_get_local_qpn(rep_msg));	param->starting_psn = be32_to_cpu(cm_rep_get_starting_psn(rep_msg));	param->responder_resources = rep_msg->initiator_depth;	param->initiator_depth = rep_msg->resp_resources;	param->target_ack_delay = cm_rep_get_target_ack_delay(rep_msg);	param->failover_accepted = cm_rep_get_failover(rep_msg);	param->flow_control = cm_rep_get_flow_ctrl(rep_msg);	param->rnr_retry_count = cm_rep_get_rnr_retry_count(rep_msg);	param->srq = cm_rep_get_srq(rep_msg);	work->cm_event.private_data = &rep_msg->private_data;}static void cm_dup_rep_handler(struct cm_work *work){	struct cm_id_private *cm_id_priv;	struct cm_rep_msg *rep_msg;	struct ib_mad_send_buf *msg = NULL;	int ret;	rep_msg = (struct cm_rep_msg *) work->mad_recv_wc->recv_buf.mad;	cm_id_priv = cm_acquire_id(rep_msg->remote_comm_id,				   rep_msg->local_comm_id);	if (!cm_id_priv)		return;	ret = cm_alloc_response_msg(work->port, work->mad_recv_wc, &msg);	if (ret)		goto deref;	spin_lock_irq(&cm_id_priv->lock);	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_irq(&cm_id_priv->lock);	ret = ib_post_send_mad(msg, NULL);	if (ret)		goto free;	goto deref;unlock:	spin_unlock_irq(&cm_id_priv->lock);free:	cm_free_msg(msg);deref:	cm_deref_id(cm_id_priv);}static int cm_rep_handler(struct cm_work *work){	struct cm_id_private *cm_id_priv;	struct cm_rep_msg *rep_msg;	int ret;	rep_msg = (struct cm_rep_msg *)work->mad_recv_wc->recv_buf.mad;	cm_id_priv = cm_acquire_id(rep_msg->remote_comm_id, 0);	if (!cm_id_priv) {		cm_dup_rep_handler(work);		return -EINVAL;	}	cm_format_rep_event(work);	spin_lock_irq(&cm_id_priv->lock);	switch (cm_id_priv->id.state) {	case IB_CM_REQ_SENT:	case IB_CM_MRA_REQ_RCVD:		break;	default:		spin_unlock_irq(&cm_id_priv->lock);		ret = -EINVAL;		goto error;	}	cm_id_priv->timewait_info->work.remote_id = rep_msg->local_comm_id;	cm_id_priv->timewait_info->remote_ca_guid = rep_msg->local_ca_guid;	cm_id_priv->timewait_info->remote_qpn = cm_rep_get_local_qpn(rep_msg);	spin_lock(&cm.lock);	/* Check for duplicate REP. */	if (cm_insert_remote_id(cm_id_priv->timewait_info)) {		spin_unlock(&cm.lock);		spin_unlock_irq(&cm_id_priv->lock);		ret = -EINVAL;		goto error;	}	/* Check for a stale connection. */	if (cm_insert_remote_qpn(cm_id_priv->timewait_info)) {		rb_erase(&cm_id_priv->timewait_info->remote_id_node,			 &cm.remote_id_table);		cm_id_priv->timewait_info->inserted_remote_id = 0;		spin_unlock(&cm.lock);		spin_unlock_irq(&cm_id_priv->lock);		cm_issue_rej(work->port, work->mad_recv_wc,			     IB_CM_REJ_STALE_CONN, CM_MSG_RESPONSE_REP,			     NULL, 0);		ret = -EINVAL;		goto error;	}	spin_unlock(&cm.lock);	cm_id_priv->id.state = IB_CM_REP_RCVD;	cm_id_priv->id.remote_id = rep_msg->local_comm_id;	cm_id_priv->remote_qpn = cm_rep_get_local_qpn(rep_msg);	cm_id_priv->initiator_depth = rep_msg->resp_resources;	cm_id_priv->responder_resources = rep_msg->initiator_depth;	cm_id_priv->sq_psn = cm_rep_get_starting_psn(rep_msg);	cm_id_priv->rnr_retry_count = cm_rep_get_rnr_retry_count(rep_msg);	cm_id_priv->target_ack_delay = cm_rep_get_target_ack_delay(rep_msg);	cm_id_priv->av.timeout =			cm_ack_timeout(cm_id_priv->target_ack_delay,				       cm_id_priv->av.timeout - 1);	cm_id_priv->alt_av.timeout =			cm_ack_timeout(cm_id_priv->target_ack_delay,				       cm_id_priv->alt_av.timeout - 1);	/* todo: handle peer_to_peer */	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_irq(&cm_id_priv->lock);	if (ret)		cm_process_work(cm_id_priv, work);	else		cm_deref_id(cm_id_priv);	return 0;error:	cm_deref_id(cm_id_priv);	return ret;}static int cm_establish_handler(struct cm_work *work){	struct cm_id_private *cm_id_priv;	int ret;	/* See comment in cm_establish about lookup. */	cm_id_priv = cm_acquire_id(work->local_id, work->remote_id);	if (!cm_id_priv)		return -EINVAL;	spin_lock_irq(&cm_id_priv->lock);	if (cm_id_priv->id.state != IB_CM_ESTABLISHED) {		spin_unlock_irq(&cm_id_priv->lock);		goto out;	}	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_irq(&cm_id_priv->lock);	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;}static int cm_rtu_handler(struct cm_work *work){	struct cm_id_private *cm_id_priv;	struct cm_rtu_msg *rtu_msg;	int ret;	rtu_msg = (struct cm_rtu_msg *)work->mad_recv_wc->recv_buf.mad;	cm_id_priv = cm_acquire_id(rtu_msg->remote_comm_id,				   rtu_msg->local_comm_id);	if (!cm_id_priv)		return -EINVAL;	work->cm_event.private_data = &rtu_msg->private_data;	spin_lock_irq(&cm_id_priv->lock);	if (cm_id_priv->id.state != IB_CM_REP_SENT &&	    cm_id_priv->id.state != IB_CM_MRA_REP_RCVD) {		spin_unlock_irq(&cm_id_priv->lock);		goto out;	}	cm_id_priv->id.state = IB_CM_ESTABLISHED;	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_irq(&cm_id_priv->lock);	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;}static void cm_format_dreq(struct cm_dreq_msg *dreq_msg,

⌨️ 快捷键说明

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