📄 iser_initiator.c
字号:
data_buf = &iser_ctask->data[ISER_DIR_OUT]; if (scsi_sg_count(sc)) { /* using a scatter list */ data_buf->buf = scsi_sglist(sc); data_buf->size = scsi_sg_count(sc); } data_buf->data_len = scsi_bufflen(sc); if (hdr->flags & ISCSI_FLAG_CMD_READ) { err = iser_prepare_read_cmd(ctask, edtl); if (err) goto send_command_error; } if (hdr->flags & ISCSI_FLAG_CMD_WRITE) { err = iser_prepare_write_cmd(ctask, ctask->imm_count, ctask->imm_count + ctask->unsol_count, edtl); if (err) goto send_command_error; } iser_reg_single(iser_conn->ib_conn->device, send_dto->regd[0], DMA_TO_DEVICE); if (iser_post_receive_control(conn) != 0) { iser_err("post_recv failed!\n"); err = -ENOMEM; goto send_command_error; } iser_ctask->status = ISER_TASK_STATUS_STARTED; err = iser_post_send(&iser_ctask->desc); if (!err) return 0;send_command_error: iser_dto_buffs_release(send_dto); iser_err("conn %p failed ctask->itt %d err %d\n",conn, ctask->itt, err); return err;}/** * iser_send_data_out - send data out PDU */int iser_send_data_out(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, struct iscsi_data *hdr){ struct iscsi_iser_conn *iser_conn = conn->dd_data; struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data; struct iser_desc *tx_desc = NULL; struct iser_dto *send_dto = NULL; unsigned long buf_offset; unsigned long data_seg_len; unsigned int itt; int err = 0; if (!iser_conn_state_comp(iser_conn->ib_conn, ISER_CONN_UP)) { iser_err("Failed to send, conn: 0x%p is not up\n", iser_conn->ib_conn); return -EPERM; } if (iser_check_xmit(conn, ctask)) return -ENOBUFS; itt = ntohl(hdr->itt); data_seg_len = ntoh24(hdr->dlength); buf_offset = ntohl(hdr->offset); iser_dbg("%s itt %d dseg_len %d offset %d\n", __func__,(int)itt,(int)data_seg_len,(int)buf_offset); tx_desc = kmem_cache_alloc(ig.desc_cache, GFP_NOIO); if (tx_desc == NULL) { iser_err("Failed to alloc desc for post dataout\n"); return -ENOMEM; } tx_desc->type = ISCSI_TX_DATAOUT; memcpy(&tx_desc->iscsi_header, hdr, sizeof(struct iscsi_hdr)); /* build the tx desc regd header and add it to the tx desc dto */ send_dto = &tx_desc->dto; send_dto->ctask = iser_ctask; iser_create_send_desc(iser_conn, tx_desc); iser_reg_single(iser_conn->ib_conn->device, send_dto->regd[0], DMA_TO_DEVICE); /* all data was registered for RDMA, we can use the lkey */ iser_dto_add_regd_buff(send_dto, &iser_ctask->rdma_regd[ISER_DIR_OUT], buf_offset, data_seg_len); if (buf_offset + data_seg_len > iser_ctask->data[ISER_DIR_OUT].data_len) { iser_err("Offset:%ld & DSL:%ld in Data-Out " "inconsistent with total len:%ld, itt:%d\n", buf_offset, data_seg_len, iser_ctask->data[ISER_DIR_OUT].data_len, itt); err = -EINVAL; goto send_data_out_error; } iser_dbg("data-out itt: %d, offset: %ld, sz: %ld\n", itt, buf_offset, data_seg_len); err = iser_post_send(tx_desc); if (!err) return 0;send_data_out_error: iser_dto_buffs_release(send_dto); kmem_cache_free(ig.desc_cache, tx_desc); iser_err("conn %p failed err %d\n",conn, err); return err;}int iser_send_control(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask){ struct iscsi_iser_conn *iser_conn = conn->dd_data; struct iser_desc *mdesc = mtask->dd_data; struct iser_dto *send_dto = NULL; unsigned long data_seg_len; int err = 0; struct iser_regd_buf *regd_buf; struct iser_device *device; if (!iser_conn_state_comp(iser_conn->ib_conn, ISER_CONN_UP)) { iser_err("Failed to send, conn: 0x%p is not up\n", iser_conn->ib_conn); return -EPERM; } if (iser_check_xmit(conn,mtask)) return -ENOBUFS; /* build the tx desc regd header and add it to the tx desc dto */ mdesc->type = ISCSI_TX_CONTROL; send_dto = &mdesc->dto; send_dto->ctask = NULL; iser_create_send_desc(iser_conn, mdesc); device = iser_conn->ib_conn->device; iser_reg_single(device, send_dto->regd[0], DMA_TO_DEVICE); data_seg_len = ntoh24(mtask->hdr->dlength); if (data_seg_len > 0) { regd_buf = &mdesc->data_regd_buf; memset(regd_buf, 0, sizeof(struct iser_regd_buf)); regd_buf->device = device; regd_buf->virt_addr = mtask->data; regd_buf->data_size = mtask->data_count; iser_reg_single(device, regd_buf, DMA_TO_DEVICE); iser_dto_add_regd_buff(send_dto, regd_buf, 0, data_seg_len); } if (iser_post_receive_control(conn) != 0) { iser_err("post_rcv_buff failed!\n"); err = -ENOMEM; goto send_control_error; } err = iser_post_send(mdesc); if (!err) return 0;send_control_error: iser_dto_buffs_release(send_dto); iser_err("conn %p failed err %d\n",conn, err); return err;}/** * iser_rcv_dto_completion - recv DTO completion */void iser_rcv_completion(struct iser_desc *rx_desc, unsigned long dto_xfer_len){ struct iser_dto *dto = &rx_desc->dto; struct iscsi_iser_conn *conn = dto->ib_conn->iser_conn; struct iscsi_session *session = conn->iscsi_conn->session; struct iscsi_cmd_task *ctask; struct iscsi_iser_cmd_task *iser_ctask; struct iscsi_hdr *hdr; char *rx_data = NULL; int rx_data_len = 0; unsigned int itt; unsigned char opcode; hdr = &rx_desc->iscsi_header; iser_dbg("op 0x%x itt 0x%x\n", hdr->opcode,hdr->itt); if (dto_xfer_len > ISER_TOTAL_HEADERS_LEN) { /* we have data */ rx_data_len = dto_xfer_len - ISER_TOTAL_HEADERS_LEN; rx_data = dto->regd[1]->virt_addr; rx_data += dto->offset[1]; } opcode = hdr->opcode & ISCSI_OPCODE_MASK; if (opcode == ISCSI_OP_SCSI_CMD_RSP) { itt = get_itt(hdr->itt); /* mask out cid and age bits */ if (!(itt < session->cmds_max)) iser_err("itt can't be matched to task!!!" "conn %p opcode %d cmds_max %d itt %d\n", conn->iscsi_conn,opcode,session->cmds_max,itt); /* use the mapping given with the cmds array indexed by itt */ ctask = (struct iscsi_cmd_task *)session->cmds[itt]; iser_ctask = ctask->dd_data; iser_dbg("itt %d ctask %p\n",itt,ctask); iser_ctask->status = ISER_TASK_STATUS_COMPLETED; iser_ctask_rdma_finalize(iser_ctask); } iser_dto_buffs_release(dto); iscsi_iser_recv(conn->iscsi_conn, hdr, rx_data, rx_data_len); kfree(rx_desc->data); kmem_cache_free(ig.desc_cache, rx_desc); /* decrementing conn->post_recv_buf_count only --after-- freeing the * * task eliminates the need to worry on tasks which are completed in * * parallel to the execution of iser_conn_term. So the code that waits * * for the posted rx bufs refcount to become zero handles everything */ atomic_dec(&conn->ib_conn->post_recv_buf_count);}void iser_snd_completion(struct iser_desc *tx_desc){ struct iser_dto *dto = &tx_desc->dto; struct iser_conn *ib_conn = dto->ib_conn; struct iscsi_iser_conn *iser_conn = ib_conn->iser_conn; struct iscsi_conn *conn = iser_conn->iscsi_conn; struct iscsi_mgmt_task *mtask; int resume_tx = 0; iser_dbg("Initiator, Data sent dto=0x%p\n", dto); iser_dto_buffs_release(dto); if (tx_desc->type == ISCSI_TX_DATAOUT) kmem_cache_free(ig.desc_cache, tx_desc); if (atomic_read(&iser_conn->ib_conn->post_send_buf_count) == ISER_QP_MAX_REQ_DTOS) resume_tx = 1; atomic_dec(&ib_conn->post_send_buf_count); if (resume_tx) { iser_dbg("%ld resuming tx\n",jiffies); scsi_queue_work(conn->session->host, &conn->xmitwork); } if (tx_desc->type == ISCSI_TX_CONTROL) { /* this arithmetic is legal by libiscsi dd_data allocation */ mtask = (void *) ((long)(void *)tx_desc - sizeof(struct iscsi_mgmt_task)); if (mtask->hdr->itt == RESERVED_ITT) { struct iscsi_session *session = conn->session; spin_lock(&conn->session->lock); list_del(&mtask->running); __kfifo_put(session->mgmtpool.queue, (void*)&mtask, sizeof(void*)); spin_unlock(&session->lock); } }}void iser_ctask_rdma_init(struct iscsi_iser_cmd_task *iser_ctask){ iser_ctask->status = ISER_TASK_STATUS_INIT; iser_ctask->dir[ISER_DIR_IN] = 0; iser_ctask->dir[ISER_DIR_OUT] = 0; iser_ctask->data[ISER_DIR_IN].data_len = 0; iser_ctask->data[ISER_DIR_OUT].data_len = 0; memset(&iser_ctask->rdma_regd[ISER_DIR_IN], 0, sizeof(struct iser_regd_buf)); memset(&iser_ctask->rdma_regd[ISER_DIR_OUT], 0, sizeof(struct iser_regd_buf));}void iser_ctask_rdma_finalize(struct iscsi_iser_cmd_task *iser_ctask){ int deferred; int is_rdma_aligned = 1; struct iser_regd_buf *regd; /* if we were reading, copy back to unaligned sglist, * anyway dma_unmap and free the copy */ if (iser_ctask->data_copy[ISER_DIR_IN].copy_buf != NULL) { is_rdma_aligned = 0; iser_finalize_rdma_unaligned_sg(iser_ctask, ISER_DIR_IN); } if (iser_ctask->data_copy[ISER_DIR_OUT].copy_buf != NULL) { is_rdma_aligned = 0; iser_finalize_rdma_unaligned_sg(iser_ctask, ISER_DIR_OUT); } if (iser_ctask->dir[ISER_DIR_IN]) { regd = &iser_ctask->rdma_regd[ISER_DIR_IN]; deferred = iser_regd_buff_release(regd); if (deferred) { iser_err("%d references remain for BUF-IN rdma reg\n", atomic_read(®d->ref_count)); } } if (iser_ctask->dir[ISER_DIR_OUT]) { regd = &iser_ctask->rdma_regd[ISER_DIR_OUT]; deferred = iser_regd_buff_release(regd); if (deferred) { iser_err("%d references remain for BUF-OUT rdma reg\n", atomic_read(®d->ref_count)); } } /* if the data was unaligned, it was already unmapped and then copied */ if (is_rdma_aligned) iser_dma_unmap_task_data(iser_ctask);}void iser_dto_buffs_release(struct iser_dto *dto){ int i; for (i = 0; i < dto->regd_vector_len; i++) iser_regd_buff_release(dto->regd[i]);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -