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

📄 iser_verbs.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	}	return;failure:	iser_connect_error(cma_id);}static void iser_connected_handler(struct rdma_cm_id *cma_id){	struct iser_conn *ib_conn;	ib_conn = (struct iser_conn *)cma_id->context;	ib_conn->state = ISER_CONN_UP;	wake_up_interruptible(&ib_conn->wait);}static void iser_disconnected_handler(struct rdma_cm_id *cma_id){	struct iser_conn *ib_conn;	ib_conn = (struct iser_conn *)cma_id->context;	ib_conn->disc_evt_flag = 1;	/* getting here when the state is UP means that the conn is being *	 * terminated asynchronously from the iSCSI layer's perspective.  */	if (iser_conn_state_comp_exch(ib_conn, ISER_CONN_UP,				      ISER_CONN_TERMINATING))		iscsi_conn_failure(ib_conn->iser_conn->iscsi_conn,				   ISCSI_ERR_CONN_FAILED);	/* Complete the termination process if no posts are pending */	if ((atomic_read(&ib_conn->post_recv_buf_count) == 0) &&	    (atomic_read(&ib_conn->post_send_buf_count) == 0)) {		ib_conn->state = ISER_CONN_DOWN;		wake_up_interruptible(&ib_conn->wait);	}}static int iser_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event){	int ret = 0;	iser_err("event %d conn %p id %p\n",event->event,cma_id->context,cma_id);	switch (event->event) {	case RDMA_CM_EVENT_ADDR_RESOLVED:		iser_addr_handler(cma_id);		break;	case RDMA_CM_EVENT_ROUTE_RESOLVED:		iser_route_handler(cma_id);		break;	case RDMA_CM_EVENT_ESTABLISHED:		iser_connected_handler(cma_id);		break;	case RDMA_CM_EVENT_ADDR_ERROR:	case RDMA_CM_EVENT_ROUTE_ERROR:	case RDMA_CM_EVENT_CONNECT_ERROR:	case RDMA_CM_EVENT_UNREACHABLE:	case RDMA_CM_EVENT_REJECTED:		iser_err("event: %d, error: %d\n", event->event, event->status);		iser_connect_error(cma_id);		break;	case RDMA_CM_EVENT_DISCONNECTED:		iser_disconnected_handler(cma_id);		break;	case RDMA_CM_EVENT_DEVICE_REMOVAL:		BUG();		break;	case RDMA_CM_EVENT_CONNECT_RESPONSE:		BUG();		break;	case RDMA_CM_EVENT_CONNECT_REQUEST:	default:		break;	}	return ret;}int iser_conn_init(struct iser_conn **ibconn){	struct iser_conn *ib_conn;	ib_conn = kzalloc(sizeof *ib_conn, GFP_KERNEL);	if (!ib_conn) {		iser_err("can't alloc memory for struct iser_conn\n");		return -ENOMEM;	}	ib_conn->state = ISER_CONN_INIT;	init_waitqueue_head(&ib_conn->wait);	atomic_set(&ib_conn->post_recv_buf_count, 0);	atomic_set(&ib_conn->post_send_buf_count, 0);	INIT_LIST_HEAD(&ib_conn->conn_list);	spin_lock_init(&ib_conn->lock);	*ibconn = ib_conn;	return 0;} /** * starts the process of connecting to the target * sleeps untill the connection is established or rejected */int iser_connect(struct iser_conn   *ib_conn,		 struct sockaddr_in *src_addr,		 struct sockaddr_in *dst_addr,		 int                 non_blocking){	struct sockaddr *src, *dst;	int err = 0;	sprintf(ib_conn->name,"%d.%d.%d.%d:%d",		NIPQUAD(dst_addr->sin_addr.s_addr), dst_addr->sin_port);	/* the device is known only --after-- address resolution */	ib_conn->device = NULL;	iser_err("connecting to: %d.%d.%d.%d, port 0x%x\n",		 NIPQUAD(dst_addr->sin_addr), dst_addr->sin_port);	ib_conn->state = ISER_CONN_PENDING;	ib_conn->cma_id = rdma_create_id(iser_cma_handler,					     (void *)ib_conn,					     RDMA_PS_TCP);	if (IS_ERR(ib_conn->cma_id)) {		err = PTR_ERR(ib_conn->cma_id);		iser_err("rdma_create_id failed: %d\n", err);		goto id_failure;	}	src = (struct sockaddr *)src_addr;	dst = (struct sockaddr *)dst_addr;	err = rdma_resolve_addr(ib_conn->cma_id, src, dst, 1000);	if (err) {		iser_err("rdma_resolve_addr failed: %d\n", err);		goto addr_failure;	}	if (!non_blocking) {		wait_event_interruptible(ib_conn->wait,					 (ib_conn->state != ISER_CONN_PENDING));		if (ib_conn->state != ISER_CONN_UP) {			err =  -EIO;			goto connect_failure;		}	}	mutex_lock(&ig.connlist_mutex);	list_add(&ib_conn->conn_list, &ig.connlist);	mutex_unlock(&ig.connlist_mutex);	return 0;id_failure:	ib_conn->cma_id = NULL;addr_failure:	ib_conn->state = ISER_CONN_DOWN;connect_failure:	iser_conn_release(ib_conn);	return err;}/** * iser_reg_page_vec - Register physical memory * * returns: 0 on success, errno code on failure */int iser_reg_page_vec(struct iser_conn     *ib_conn,		      struct iser_page_vec *page_vec,		      struct iser_mem_reg  *mem_reg){	struct ib_pool_fmr *mem;	u64		   io_addr;	u64		   *page_list;	int		   status;	page_list = page_vec->pages;	io_addr	  = page_list[0];	mem  = ib_fmr_pool_map_phys(ib_conn->fmr_pool,				    page_list,				    page_vec->length,				    io_addr);	if (IS_ERR(mem)) {		status = (int)PTR_ERR(mem);		iser_err("ib_fmr_pool_map_phys failed: %d\n", status);		return status;	}	mem_reg->lkey  = mem->fmr->lkey;	mem_reg->rkey  = mem->fmr->rkey;	mem_reg->len   = page_vec->length * SIZE_4K;	mem_reg->va    = io_addr;	mem_reg->is_fmr = 1;	mem_reg->mem_h = (void *)mem;	mem_reg->va   += page_vec->offset;	mem_reg->len   = page_vec->data_size;	iser_dbg("PHYSICAL Mem.register, [PHYS p_array: 0x%p, sz: %d, "		 "entry[0]: (0x%08lx,%ld)] -> "		 "[lkey: 0x%08X mem_h: 0x%p va: 0x%08lX sz: %ld]\n",		 page_vec, page_vec->length,		 (unsigned long)page_vec->pages[0],		 (unsigned long)page_vec->data_size,		 (unsigned int)mem_reg->lkey, mem_reg->mem_h,		 (unsigned long)mem_reg->va, (unsigned long)mem_reg->len);	return 0;}/** * Unregister (previosuly registered) memory. */void iser_unreg_mem(struct iser_mem_reg *reg){	int ret;	iser_dbg("PHYSICAL Mem.Unregister mem_h %p\n",reg->mem_h);	ret = ib_fmr_pool_unmap((struct ib_pool_fmr *)reg->mem_h);	if (ret)		iser_err("ib_fmr_pool_unmap failed %d\n", ret);	reg->mem_h = NULL;}/** * iser_dto_to_iov - builds IOV from a dto descriptor */static void iser_dto_to_iov(struct iser_dto *dto, struct ib_sge *iov, int iov_len){	int		     i;	struct ib_sge	     *sge;	struct iser_regd_buf *regd_buf;	if (dto->regd_vector_len > iov_len) {		iser_err("iov size %d too small for posting dto of len %d\n",			 iov_len, dto->regd_vector_len);		BUG();	}	for (i = 0; i < dto->regd_vector_len; i++) {		sge	    = &iov[i];		regd_buf  = dto->regd[i];		sge->addr   = regd_buf->reg.va;		sge->length = regd_buf->reg.len;		sge->lkey   = regd_buf->reg.lkey;		if (dto->used_sz[i] > 0)  /* Adjust size */			sge->length = dto->used_sz[i];		/* offset and length should not exceed the regd buf length */		if (sge->length + dto->offset[i] > regd_buf->reg.len) {			iser_err("Used len:%ld + offset:%d, exceed reg.buf.len:"				 "%ld in dto:0x%p [%d], va:0x%08lX\n",				 (unsigned long)sge->length, dto->offset[i],				 (unsigned long)regd_buf->reg.len, dto, i,				 (unsigned long)sge->addr);			BUG();		}		sge->addr += dto->offset[i]; /* Adjust offset */	}}/** * iser_post_recv - Posts a receive buffer. * * returns 0 on success, -1 on failure */int iser_post_recv(struct iser_desc *rx_desc){	int		  ib_ret, ret_val = 0;	struct ib_recv_wr recv_wr, *recv_wr_failed;	struct ib_sge	  iov[2];	struct iser_conn  *ib_conn;	struct iser_dto   *recv_dto = &rx_desc->dto;	/* Retrieve conn */	ib_conn = recv_dto->ib_conn;	iser_dto_to_iov(recv_dto, iov, 2);	recv_wr.next	= NULL;	recv_wr.sg_list = iov;	recv_wr.num_sge = recv_dto->regd_vector_len;	recv_wr.wr_id	= (unsigned long)rx_desc;	atomic_inc(&ib_conn->post_recv_buf_count);	ib_ret	= ib_post_recv(ib_conn->qp, &recv_wr, &recv_wr_failed);	if (ib_ret) {		iser_err("ib_post_recv failed ret=%d\n", ib_ret);		atomic_dec(&ib_conn->post_recv_buf_count);		ret_val = -1;	}	return ret_val;}/** * iser_start_send - Initiate a Send DTO operation * * returns 0 on success, -1 on failure */int iser_post_send(struct iser_desc *tx_desc){	int		  ib_ret, ret_val = 0;	struct ib_send_wr send_wr, *send_wr_failed;	struct ib_sge	  iov[MAX_REGD_BUF_VECTOR_LEN];	struct iser_conn  *ib_conn;	struct iser_dto   *dto = &tx_desc->dto;	ib_conn = dto->ib_conn;	iser_dto_to_iov(dto, iov, MAX_REGD_BUF_VECTOR_LEN);	send_wr.next	   = NULL;	send_wr.wr_id	   = (unsigned long)tx_desc;	send_wr.sg_list	   = iov;	send_wr.num_sge	   = dto->regd_vector_len;	send_wr.opcode	   = IB_WR_SEND;	send_wr.send_flags = dto->notify_enable ? IB_SEND_SIGNALED : 0;	atomic_inc(&ib_conn->post_send_buf_count);	ib_ret = ib_post_send(ib_conn->qp, &send_wr, &send_wr_failed);	if (ib_ret) {		iser_err("Failed to start SEND DTO, dto: 0x%p, IOV len: %d\n",			 dto, dto->regd_vector_len);		iser_err("ib_post_send failed, ret:%d\n", ib_ret);		atomic_dec(&ib_conn->post_send_buf_count);		ret_val = -1;	}	return ret_val;}static void iser_handle_comp_error(struct iser_desc *desc){	struct iser_dto  *dto     = &desc->dto;	struct iser_conn *ib_conn = dto->ib_conn;	iser_dto_buffs_release(dto);	if (desc->type == ISCSI_RX) {		kfree(desc->data);		kmem_cache_free(ig.desc_cache, desc);		atomic_dec(&ib_conn->post_recv_buf_count);	} else { /* type is TX control/command/dataout */		if (desc->type == ISCSI_TX_DATAOUT)			kmem_cache_free(ig.desc_cache, desc);		atomic_dec(&ib_conn->post_send_buf_count);	}	if (atomic_read(&ib_conn->post_recv_buf_count) == 0 &&	    atomic_read(&ib_conn->post_send_buf_count) == 0) {		/* getting here when the state is UP means that the conn is *		 * being terminated asynchronously from the iSCSI layer's   *		 * perspective.                                             */		if (iser_conn_state_comp_exch(ib_conn, ISER_CONN_UP,		    ISER_CONN_TERMINATING))			iscsi_conn_failure(ib_conn->iser_conn->iscsi_conn,					   ISCSI_ERR_CONN_FAILED);		/* complete the termination process if disconnect event was delivered *		 * note there are no more non completed posts to the QP               */		if (ib_conn->disc_evt_flag) {			ib_conn->state = ISER_CONN_DOWN;			wake_up_interruptible(&ib_conn->wait);		}	}}static void iser_cq_tasklet_fn(unsigned long data){	 struct iser_device  *device = (struct iser_device *)data;	 struct ib_cq	     *cq = device->cq;	 struct ib_wc	     wc;	 struct iser_desc    *desc;	 unsigned long	     xfer_len;	while (ib_poll_cq(cq, 1, &wc) == 1) {		desc	 = (struct iser_desc *) (unsigned long) wc.wr_id;		BUG_ON(desc == NULL);		if (wc.status == IB_WC_SUCCESS) {			if (desc->type == ISCSI_RX) {				xfer_len = (unsigned long)wc.byte_len;				iser_rcv_completion(desc, xfer_len);			} else /* type == ISCSI_TX_CONTROL/SCSI_CMD/DOUT */				iser_snd_completion(desc);		} else {			iser_err("comp w. error op %d status %d\n",desc->type,wc.status);			iser_handle_comp_error(desc);		}	}	/* #warning "it is assumed here that arming CQ only once its empty" *	 * " would not cause interrupts to be missed"                       */	ib_req_notify_cq(cq, IB_CQ_NEXT_COMP);}static void iser_cq_callback(struct ib_cq *cq, void *cq_context){	struct iser_device  *device = (struct iser_device *)cq_context;	tasklet_schedule(&device->cq_tasklet);}

⌨️ 快捷键说明

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